<?php

namespace Mnv\Models;

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

/**
 * Class TypeContentField
 * @package Mnv\Models
 */
class TypeContentField extends Model
{
    /** @var string */
    protected string $table = 'type_content_fields';

    /** @var string  */
    protected string $primaryKey = 'fieldId';

    /** @var string  */
    protected string $orderBy = 'orderBy ASC';

    /** @var int|null  */
    public $typeId;

    /** @var array|mixed  */
    public $field_data = [];

    /** @var  */
    public $properties;

    public $fieldIds = [];

    /** @var array|string[]  */
    private static array $typeFields = [
        'I' => 'Поле ввода',        // I - text
        'D' => 'Дата',              // D - data
        'C' => 'Флажок',            // C - checkbox
        'R' => 'Радиогруппа',       // R - radio
        'S' => 'Список вариантов',  // S - select
//        'M' => 'Список вариантов мульти',  // M - select multiple
        'T' => 'Текстовая область', // T - textarea
//        'F' => 'Файл'        // F - file
    ];


    public function __construct(Request $request)
    {
        $this->id           = $request->get('id',''); //  getRequestVar('id',''),
        $this->data         = $request->get('field', ''); // getRequestVar('typeId',''),
        $this->typeId       = $request->get('typeId',''); // getRequestVar('field','', true),
        $this->field_data   = $request->get('field_data',''); // getRequestVar('field_data','', true)
        $this->fieldIds     = $request->get('ids','');

    }


    /**
     * Проверка на совпадение и получение fileName
     *
     * @param string|null $fileName
     * @return mixed|string|null
     */
    public function checkFileName(string $fileName)
    {
        if (!empty($this->id)) connect()->where($this->primaryKey, '<>', $this->id);
        if ($fileName = connect()->table($this->table)->select('fileName')->where('typeId', $this->typeId)->where('LOWER(fileName)', strtolower($fileName))->getValue()) {
            return $fileName;
        }

        return null;
    }

    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']       = $this->getMaxValue('orderBy') + 1;
            if ($this->id = $this->insert($data)) {
                if ($data['type'] == 'R' || $data['type'] == 'S') {
                    $this->createColumn($data['fileName'], $data['type_sql']);
                    $this->setProperties();
                }
                return true;
            }
        } else {

            if ($this->update($data)) {
                if ($data['type'] == 'R' || $data['type'] == 'S') {
                    $this->createColumn($data['fileName'], $data['type_sql']);
                    $this->setProperties();
                }

                return true;
            }
        }

        return false;
    }


    protected function setProperties()
    {

        if (is_array($this->field_data)) {
            $fieldDataIds = array();
            foreach($this->field_data as &$fieldData) {

                /** если уже существует вариант продукта то обновляем его в противном случае добавляем */
                if (isset($fieldData['propertyId']) && !empty($fieldData['propertyId'])) {
                    /** обновляем */
                    $this->updateProperty($fieldData['propertyId'], $fieldData);

                } else {
                    /** добавление */
                    $fieldData['fieldId'] = $this->id;
                    $fieldData['propertyId'] = $this->addProperty($fieldData);
                }

                /** возвращаем  */
                $fieldData = $this->getProperty($fieldData['propertyId']); // ОШИБКА
                if (!empty($fieldData['propertyId'])) {
                    $fieldDataIds[] = $fieldData['propertyId'];
                }
            }

            /** возвращает */
            $currentProperties = $this->getLisProperties($this->id);

            /** Удаляем */
            foreach($currentProperties as $currentProperty) {
                if (!in_array($currentProperty['propertyId'], $fieldDataIds, true)) {
                    $this->deleteProperty($currentProperty['propertyId']);
                }
            }
            /** Отсортировать */
            asort($fieldDataIds);
            $i = 0;
            foreach($fieldDataIds as $fieldDataId) {
                /** обновляем вариант продукта */
                $this->updateProperty($fieldDataIds[$i], ['orderBy' => $fieldDataId]);
                $i++;
            }

        }
    }


    public function remove(): bool
    {
        // получить поле
        if (!empty($this->id) && $field = connect()->table($this->table)->where($this->primaryKey, $this->id)->get('array')) {
            // удалить поле
            connect()->table($this->table)->where($this->primaryKey, $this->id)->delete();
//            // удалить value
            connect()->table('type_content_field_data')->where('fileName', $field['fileName'])->delete();
//            // удалить property
            connect()->table('type_content_field_property')->where($this->primaryKey, $this->id)->delete();

            if ($field['type'] == 'R' || $field['type'] == 'S') {
               $this->removeColumn($field['fileName']);
            }

            return true;
        }

        return false;

    }

    protected function createColumn($columnName, $sql = null): bool
    {
        $Existence_column = connect()->table('articles')->isColumn($columnName)->fetch();
        if (!$Existence_column) {
            connect()->table('articles')->createColumn($columnName, $sql)->exec();
            return true;
//         print_r(connect()->getQuery().PHP_EOL);
        }

        return false;
    }

    protected function removeColumn($columnName): bool
    {
        $Existence_column = connect()->table('articles')->isColumn($columnName)->fetch();
        if ($Existence_column) {
           connect()->table('articles')->removeColumn($columnName)->exec();
            return true;
        }
        return false;
    }



//    public function reorder($fieldIds)
//    {
//        $i = 0;
//        foreach ($fieldIds as $fieldId) {
//            $i++;
//            connect()->table($this->table)->where($this->primaryKey, $fieldId)->update(['orderBy' => $i]);
//        }
//    }

    public function getProperties()
    {
        if (!empty($this->id)) {
            $this->properties = connect()->table('type_content_field_property')->orderBy('propertyId ASC')->where($this->primaryKey, $this->id)->getAll('array');
        }

    }

    public function getLisProperties($fieldId)
    {
        if (!empty($fieldId)) {
            return connect()->table('type_content_field_property')->where($this->primaryKey,$fieldId)->orderBy('propertyKey ASC')->indexKey('propertyId')->getAllIndexes('array');
        }

        return null;
    }

    public function getProperty(int $propertyId)
    {
        if (!empty($propertyId)) {
            return connect()->table('type_content_field_property')->where('propertyId', $propertyId)->get('array');
        }

        return null;
    }

    protected function addProperty(array $property): int
    {
        return (int)connect()->table('type_content_field_property')->insert($property);
    }

    protected function updateProperty($propertyId, array $property)
    {
        connect()->table('type_content_field_property')->where('propertyId', $propertyId)->update($property);
    }

    public function deleteProperty(int $propertyId)
    {
        connect()->table('type_content_field_property')->where('propertyId', $propertyId)->delete();

    }


    /** STATIC METHODS */


    public static function getTypeFields(): array
    {
        return self::$typeFields;
    }

    public static function getNameTypeField($type): string
    {
        return self::$typeFields[$type];
    }

    public static function typeContentFields(int $typeId, ?string $status): ?array
    {
        if (!empty($status)) {
            connect()->where('status', $status);
        }
        return connect()->table('type_content_fields')->where('typeId', $typeId)->orderBy('orderBy ASC')->getAll('array');
    }

    public static function typeContentFieldProperty(string $orderBy, int $fieldId): ?array
    {
        return connect()->table('type_content_field_property')->orderBy($orderBy)->where('fieldId', $fieldId)->indexKey('propertyKey')->valueKey('name')->getAllIndexes('array');
    }

}