<?php

namespace Mnv\Models;

use Mnv\Core\Model;
use Mnv\Core\Test\Logger;
use Mnv\Http\Request;
use Mnv\Models\Exceptions\NoContentException;
use Mnv\Models\Exceptions\NotInsertContentException;
use Mnv\Models\Exceptions\NotUpdateContentException;
use Mnv\Models\Exceptions\NotContentApproveException;


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

    /** @var string  */
    protected string $table_image = 'article_images';

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

    /** @var string  */
    protected string $orderBy = 'publishedOn DESC';

    /** @var array|string[]  */
    public array $all_columns = array(
        array("id" => "articleId",			"content" => "ID",           "default" => true, "class" => "text-center text-nowrap", 'width' => '30', 'font' => 'fw-bold'),
        array("id" => "publishedOn",	    "content" => 'Дата',         "default" => true, "class" => "text-center text-nowrap", 'width' => '80', 'font' => 'fw-semibold'),
        array("id" => "title", 		        "content" => "Название",     "default" => true, "class" => "text-start", 'font' => 'fw-bold'),
        array("id" => "sectionId",			"content" => "Раздел",       "default" => true, "class" => "text-start", 'font' => 'fw-semibold'),
        array("id" => "status", 	        "content" => "Статус",       "default" => true,"class" => "text-center", 'font' => ''),
        array("id" => "summary", 			"content" => 'Описание',     "default" => true, "class" => "text-start", 'font' => ''),
        array("id" => "image", 			    "content" => 'Картинка',     "default" => false, "class" => "text-start", 'font' => ''),
    );

    /** @var string  */
    protected string $columns = 'articleId, sectionId, title, alias, url, publishedOn, publicationEnd, orderBy, isFeatured, status, typeContent, summary';

    public $field;

    /** @var array $image */
    public $image = [];

    /** @var int $imageId */
    public int $imageId;

    public string $typeContent;

    public $contentIds;


    public function __construct(Request $request)
    {
        $this->id           = $request->get('id');                      // (int) getRequestVar('id', ''),
        $this->data         = $request->get('article', '');      //  getRequestVar('article', '', true)
        $this->field        = $request->get('field', '');        // getRequestVar('field', '', true)
        $this->contentIds   = $request->get('articleIds', '');   // getRequestVar('articleIds', '', true)
    }

    /** фильтрация / сортировка */
    protected function sorting(): void
    {
        global $SECTIONS;

        if (!empty($this->filter['typeContent'])) {
            connect()->where('typeContent', $this->filter['typeContent']);
        }

        if (!empty($this->filter['status'])) {
            connect()->where('status', $this->filter['status']);
        }


        if (!empty($this->filter['query'])) {
            connect()->grouped(function($q) {
                $q->like('title', "%" . $this->filter['query'] . "%")->orLike('content', "%" . $this->filter['query'] . "%")->orLike('keywords',"%" . $this->filter['query'] . "%");
            });
        }

        if (!empty($this->filter['section']) && !empty($SECTIONS[$this->filter['section']])) {
            $sectionIds = array($this->filter['section']);
            if (!empty($SECTIONS[$this->filter['section']]['allChildren'])) {
                $sectionIds = array_merge($sectionIds, $SECTIONS[$this->filter['section']]['allChildren']);
            }
            connect()->in('sectionId', $sectionIds);
        }

        if (!empty($this->filter['dateStart']) && !empty($this->filter['dateEnd'])) {
            connect()->between('publishedOn', $this->filter['dateStart'], $this->filter['dateEnd']);
        }

    }

    /** Получение всех статей */
    public function all($limit, $page)
    {
        /** фильтрация / сортировка */
        $this->sorting();

        return parent::all($limit, $page);
    }

    /** Получение кол-во контента */
    public function total(): void
    {
        /** фильтрация / сортировка */
        $this->sorting();
        parent::total();
    }

    /**
     * Проверка на совпадение и получение fileName
     *
     * @param string|null $fileName
     * @return int|mixed|string|null
     */
    public function checkFileName(?string $fileName)
    {
        if (empty($fileName)) {
            $maxId = $this->getMaxValue($this->primaryKey);
            return $maxId ? $maxId + 1 : 1;
        }

        if (!empty($this->id)) connect()->where($this->primaryKey,'<>', $this->id);
        if ($fileName = connect()->table($this->table)->select('fileName')->where('LOWER(fileName)', strtolower($fileName))->getValue()) {
            return $fileName;
        }

        return null;
    }

    /**
     * @throws NotUpdateContentException
     * @throws NotInsertContentException
     */
    public function prepare(array $data, int $managerId): bool
    {

        $data['modifiedBy']   = $managerId;
        $data['modifiedOn']   = gmdate('Y-m-d H:i:s');
        $data['publishedOn']  = adjustTime(date('Y-m-d H:i:s', strtotime($data['publishedOn'])),  true);

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

            $data['addedBy'] = $managerId;
            $data['addedOn'] = gmdate('Y-m-d H:i:s');
            $data['orderBy'] = connect()->table($this->table)->max('orderBy')->where('typeContent', $data['typeContent'])->getValue() + 1;
            if ($this->id = $this->insert($data)) {
                $this->setProperties();
                Logger::init()->info("Добавлен новый контент «" . $data['title'] . "»", $managerId)->save();
                return true;
            }
            Logger::init()->error("Ошибка при добавление контента «" . $data['name'] . "»", $managerId)->save();

            throw new NotInsertContentException();
        }
        else {

            if ($this->update($data)) {
                $this->setProperties();
                Logger::init()->info("В контент «" . $data['title'] . "» были внесены изменения", $managerId)->save();
                return true;
            }
            Logger::init()->error("Ошибка при редактирование контента «" . $data['title'] . "»", $managerId)->save();

            throw new NotUpdateContentException();
        }

    }


    /** Удаление контента */
    public function remove(): bool
    {
        if (parent::remove()) {
            connect()->table('comments')->where($this->primaryKey, $this->id)->delete();
            connect()->table('article_images')->where($this->primaryKey, $this->id)->delete();
            connect()->table('type_content_field_data')->where($this->primaryKey, $this->id)->delete();

            return true;
        }

        return false;
    }

    /**
     * Обновление статуса
     *
     * @return bool
     * @throws NoContentException
     * @throws NotContentApproveException
     */
    public function approve(): bool
    {
        if (!empty($this->id) && $this->data = $this->get()) {
            if (connect()->table($this->table)->where($this->primaryKey,$this->id)->update(['status' => 'V'])) {
                return true;
            }
            throw new NotContentApproveException();
        }

        throw new NoContentException();
    }

    /**
     * Сортировка контента
     *
     * @param $ids
     * @param $articleIds
     */
    public function reorder($ids, $articleIds): void
    {
        foreach ($articleIds as $i => $articleId) {
            connect()->table($this->table)->where($this->primaryKey, $ids[$i])->update(['orderBy' => $articleId]);
        }
    }

    /**
     * Групповые действия
     * @param $group_action
     */
    public function group($group_action): void
    {
        if ($group_action === 'status') {
            if ($this->data = $this->get()) {
                $contentUpdate['status'] = ($this->data['status'] === 'V') ? 'H' : 'V';
                $this->statusContent($contentUpdate);
            }

        } else if ($group_action === 'remove') {
            if ($this->data = $this->get()) {
                $this->removeContent();
            }
        }
    }

    /**
     * Обновление статуса контента
     *
     * @param $contentUpdate
     * @return bool
     */
    public function statusContent($contentUpdate): bool
    {
        if (connect()->table($this->table)->where($this->primaryKey, $this->id)->update($contentUpdate)) {
            return true;
        }

        return false;
    }

    /** Групповое удаление контента */
    public function removeContent(): bool
    {
        /** удаление контента и удаление записей из базы данных прикрепленных картинок и комментариев к этому контенту */
        if (connect()->table($this->table)->where($this->primaryKey, $this->id)->delete()) {
            connect()->table('comments')->where($this->primaryKey, $this->id)->delete();
            connect()->table('article_images')->where($this->primaryKey, $this->id)->delete();

            return true;
        }

        return false;
    }


    public function setProperties()
    {
        if (is_array($this->field)) {
            $propertyIds = connect()->table('type_content_fields AS tcf')->usingJoin('type_content AS tc', 'typeId')->select('tcf.fileName')->where('tcf.status', 'V')->where('tc.fileName', $this->typeContent)->indexKey('fileName')->valueKey('fileName')->getAllIndexes('array');
//        print_r(connect()->getQuery());
//        print_r($propertyIds);

            if (!empty($propertyIds)) {
                foreach ($this->field as $fileName => $field) {
                    if (in_array($fileName, $propertyIds)) {
                        $this->updatePropertyData($this->id, $fileName, $field);
                    }
                }
            }
        }
    }

    /**
     * Обновление/вставка полей
     *
     * @param int $articleId
     * @param string $fileName
     * @param string|null $value
     */
    public function updatePropertyData(int $articleId, string $fileName, ?string $value = null)
    {
        if ($value != null) {
            connect()->table('type_content_field_data')->select('*')->replace(['articleId' => $articleId, 'fileName' => $fileName, 'value' => $value]);
        } else {
            connect()->table('type_content_field_data')->where($this->primaryKey, $articleId)->where('fileName', $fileName)->delete();
        }
    }

    public function getProperties($articleId): array
    {
        if ($result = connect()->table('type_content_field_data')
            ->usingJoin('type_content_fields', 'fileName')
            ->select('articleId, typeId, type, fieldId, fileName, name, value, orderBy')
            ->where($this->primaryKey, $articleId)
            ->where('status', 'V')
            ->orderBy('orderBy')
            ->indexKey('fileName')->valueKey('value')->getAllIndexes('array')
        ) {


            return $result;
        }

        return array();
    }

    public function getPrices($articleId)
    {

    }

}