<?php

namespace Mnv\Models\Shop;

use Mnv\Core\Model;
use Mnv\Http\Request;

/**
 * Class Options
 * @package Mnv\Models\Cars
 */
class Options extends Model
{
    protected string $table = 'options';

    protected string $primaryKey = 'optionId';

    protected string $orderBy = 'orderBy ASC';


    public $optionIds = [];
    public $options = [];

    public function __construct(Request $request)
    {

        $this->id          = $request->get('id');
        $this->data        = $request->get('features', '');
        $this->optionIds   = $request->get('optionIds', '');
        /** options  */
        $this->options = $request->get('options', '');

    }


    private function sortBy()
    {
        if (!empty($this->filter['query'])) {
            connect()->grouped(function($q) {
                $q->like('name', "%" . $this->filter['query'] . "%");
            });
        }
        if (!empty($this->filter['status'])) {
            connect()->where('status', $this->filter['status']);
        }

        connect()->whereNull('parentId',  false);

    }


    public function all($limit, $page)
    {
        $this->sortBy();

        return parent::all($limit, $page);
    }
    public function total()
    {
        $this->sortBy();

        parent::total();
    }


    public function prepare(array $data, int $managerId): bool
    {

        $data['modifiedBy']   = $managerId;
        $data['modifiedOn']   = gmdate('Y-m-d H:i:s');

        if (empty($this->id)) {

            $data['addedBy'] = $managerId;
            $data['addedOn'] = gmdate('Y-m-d H:i:s');
            $data['orderBy'] = connect()->table($this->table)->max('orderBy')->getValue() + 1;
            if ($this->id = $this->insert($data)) {
                return true;
            }
        }
        else {

            return $this->update($data);
        }

        return false;
    }



    /** Удаление */
    public function remove(): bool
    {
        /** удаление свойства */
        if (connect()->table($this->table)->where($this->primaryKey, $this->id)->delete()) {
            connect()->table($this->table)->where('parentId', $this->id)->delete();

            return true;
        }

        return false;
    }


    /** Сортировка */
    public function reorder($featureIds)
    {
        $i = 0;
        foreach ($featureIds as $featureId) {
            $i++;
            connect()->table($this->table)->where($this->primaryKey, $featureId)->update(['orderBy' => $i]);
        }
    }


    /** OPTIONS */

    public function options(): ?array
    {
        if (!empty($this->id)) {
            return connect($this->table)->where('parentId', $this->id)->orderBy('orderBy')->indexKey('optionId')->getAllIndexes('array');
        }

        return [];
    }

    public function option(int $optionId)
    {
        if (!empty($optionId)) {
            return connect($this->table)->where('optionId', $optionId)->get('array');
        }

        return null;
    }

    public function addOption(array $option): int
    {
        $option['parentId'] = $this->id;
        $option['orderBy'] = 0;

        return connect($this->table)->insert($option);
    }

    /**
     * @param int $optionId
     * @param array $option
     */
    public function updateOption(int $optionId, array $option): void
    {
        connect($this->table)->where('optionId', $optionId)->update($option);
    }

    public function removeOption(int $optionId): void
    {
        connect($this->table)->where('optionId', $optionId)->delete();
    }



    /**
     * ПОЛУЧИТЬ свойства и опции
     * @return array
     */
    public function getLevelOptions(): ?array
    {
        return connect($this->table)->select('optionId, name, type')->orderBy('orderBy ASC')->whereNull('parentId',  false)->getAll('array');

    }

    /** ПОЛУЧИТЬ опции */
    public function getSelectOptions(): ?array
    {
        if (!empty($this->filter['query'])) {
            connect()->grouped(function($q) {
                $q->like('name', "%" . $this->filter['query'] . "%");
            });
        }
        $options = connect($this->table)->select('optionId, parentId, name, type')->orderBy('orderBy ASC')->where('status', 'V')->pagination($this->filter['limit'], $this->filter['start'])->getAll('array');
        return $this->optionsBuildTreeFromArray($options, 'parentId', 'optionId', 'properties');
//        $options = connect($this->table)->select('optionId, name, type')->orderBy('orderBy ASC')->whereNull('parentId',  false)->pagination($this->filter['limit'], $this->filter['start'])->getAll('array');
//        return collect($options)->map(function ($option) {
//            $option['properties'] = connect($this->table)->select('optionId, name')->where('parentId', $option['optionId'])->orderBy('orderBy ASC')->whereNull('parentId',  true)->getAll('array');
//
//            return $option;
//        })->all();
    }



    /**
     * ПОЛУЧИТЬ свойства и опции
     * @return array
     */
    public function getOptions(): ?array
    {
        $options = connect($this->table)->select('optionId, parentId, name, type')->orderBy('orderBy ASC')->where('status', 'V')->getAll('array');
        return $this->optionsBuildTreeFromArray($options, 'parentId', 'optionId', 'properties');

//        $options = connect($this->table)->select('optionId, name, type')->orderBy('orderBy ASC')->whereNull('parentId',  false)->getAll('array');
//        return collect($options)->map(function ($option) {
//            $option['properties'] = connect($this->table)->select('optionId, name')->where('parentId', $option['optionId'])->orderBy('orderBy ASC')->whereNull('parentId',  true)->getAll('array');
//
//            return $option;
//        })->all();
    }

    private function optionsBuildTreeFromArray($items, $indexKey, $key, $subArray) {

        $childs = [];

        foreach ($items as &$item) {
            $childs[$item[$indexKey] ?? 0][] = &$item;
        }

        unset($item);

        foreach ($items as &$item) {
            if (isset($childs[$item[$key]])) {
                $item[$subArray] = $childs[$item[$key]];
            }
        }

        return $childs[0] ?? [];
    }

}