<?php

namespace Mnv\Models;

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

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

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

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

    /** @var  */
    public $bulk;


    public function __construct(Request $request)
    {
        $this->id   = $request->get('id');                 //   getRequestVar('id', ''),
        $this->data = $request->get('comment', ''); //   getRequestVar('comment','', true)
        $this->bulk = $request->get('bulk','');     //   getRequestVar('bulk','', true)
    }

    private function sorting()
    {
        /* processing search fields */
        if (!empty($this->filter['query'])) {
            connect()->grouped(function($q) {
                $q->like('content', "%" . $this->filter['query'] . "%")->orLike('authorName', "%" . $this->filter['query'] . "%")->orLike('authorEmail',"%" . $this->filter['query']. "%");
            });
        }

        if (!empty($this->filter['status'])) {
            connect()->where('status',  $this->filter['status']);
            if ($this->filter['status'] === 'pending') {
                connect()->orderBy('addedOn', 'ASC');
            } else {
                connect()->orderBy('addedOn', 'DESC');
            }
        } else {
            connect()->in('status', ['pending', 'approved']);
            connect()->orderBy('addedOn', 'DESC');
        }

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


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

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


    public function total()
    {
        $this->sorting();

        parent::total();
    }

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

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

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

            if ($this->update($data)) {
                /**  получение articleId @var  $articleId */
                $articleId = $this->getArticleId($this->id);
                /** Получение кол-ва комментариев @var $totalComments */
                $totalComments = $this->totalComments($articleId);
                /** обновление кол-ва комментариев у контента по его articleId */
                $this->updateArticleTotalComments($articleId, $totalComments);
                /** votes $article->votes */
                if ($data['status'] == 'approved') {
                    $this->setRating($articleId, $data['rating'], $this->id);
                }
//                if ($comment['status'] == 'approved' && $comment['checkRating'] == 0) {
//                    $this->setRating($articleId, $comment['rating'], $this->commentId);
//                }

                return true;
            }

        }
        return false;

    }


    /**
     * Обновление рейтинга у контента
     *
     * TODO: продумать что при сохранение не дублировать данные
     * @param $articleId
     * @param $rating
     * @param $commentId
     */
    private function setRating($articleId, $rating, $commentId)
    {
        $article = connect()->table('articles')->select('articleId, rating, votes')->where('articleId', $articleId)->get();
        if ($article) {
            $article->rating = number_format(($article->rating * $article->votes + $rating) / ($article->votes + 1), 1, '.', ',');
            $article->votes = $article->votes + 1;
            connect()->table('articles')->where('articleId','=', $article->articleId)->update(['rating' => $article->rating, 'votes' => $article->votes]);
            connect()->table($this->table)->where($this->primaryKey, $commentId)->update(['checkRating' => 1]);
        }
    }

    /**
     * получение articleId
     * @param $commentId
     * @return mixed
     */
    private function getArticleId($commentId)
    {
        return connect()->table($this->table)->select('articleId')->where($this->primaryKey,  $commentId)->getValue();
    }

    /**
     * Получение кол-ва комментариев
     * @param $articleId
     * @return array|false|mixed|string
     */
    private function totalComments($articleId) {
        return connect()->table($this->table)->count('*', 'count')->where('articleId', $articleId)->where('status', 'approved')->getValue();
    }


    /**
     * обновление кол-ва комментариев у статьи
     * @param $articleId
     * @param $totalComments
     */
    private function updateArticleTotalComments($articleId, $totalComments)
    {
        connect()->table('articles')->where('articleId','=', $articleId)->update(['totalComments' => $totalComments]);
    }

    /**
     * @param $bulk
     * @return bool
     */
    public function bulk($bulk): bool
    {
        if (!empty($bulk)) {
            $articleIds = connect()->table($this->table)->select('DISTINCT articleId')->in($this->primaryKey, array_keys($bulk))->indexKey('articleId')->getAllIndexes();

            foreach ($bulk as $commentId => $commentStatus) {
                if ($commentStatus == 1) {
                    connect()->table('comments')->where($this->primaryKey, $commentId)->update(['status' => 'approved']);
                } elseif ($commentStatus == 2) {
                    connect()->table('comments')->where($this->primaryKey, $commentId)->update(['status' => 'spam']);
                } elseif ($commentStatus == 3) {
                    connect()->table('comments')->where($this->primaryKey, $commentId)->delete();
                } elseif ($commentStatus == 0) {
                    connect()->table('comments')->where($this->primaryKey, $commentId)->update(['status' => 'pending']);
                }
            }

            /* update totalComments */
//            $commentTotals = dbQuery('comments', DB_ARRAYS, array('where'=>"articleId IN('".implode("','", $articleIds)."') AND status='approved'", 'fields'=>'articleId, COUNT(*) AS totalComments', 'group'=>'articleId', 'indexKey'=>'articleId', 'valueKey'=>'totalComments'));
//            foreach($commentTotals as $articleId=>$totalComments) dbQuery('articles', DB_UPDATE, array('where'=>"articleId='$articleId'", 'values'=>"totalComments='$totalComments'"));
            // 'indexKey'=>'articleId', 'valueKey'=>'totalComments'
            $commentTotals = connect()->table($this->table)->select('articleId, COUNT(*) AS totalComments')->in('articleId', array_keys($articleIds))
                ->where('status','approved')->groupBy('articleId')->indexKey('articleId')->valueKey('totalComments')->getAllIndexes('array');

//            print_r($commentTotals);
            /** TODO: Выдает ошибку по $articleId так как его нет  */
            foreach($commentTotals as $articleId => $totalComments) {
                connect()->table('articles')->where('articleId', $articleId)->update(['totalComments' => $totalComments]);
            }
            return true;
        }
        return false;
    }


    /**
     * получение комментариев ожидающих подтверждение
     *
     * @return array|false|mixed|string
     */
    public static function getPendingComments()
    {
        $comments =  connect()->table('comments')->where('status','pending')->getAll('array');
        foreach ($comments as $commentId => $comment) {
            $comments[$commentId]['addedOn'] = adjustTime($comment['addedOn'], false, 'd.m.Y H:i');
        }

        return $comments;
    }

    /**
     * получение кол-во комментариев ожидающих подтверждение
     *
     * @return mixed|string|null
     */
    public static function totalPendingComments()
    {
        return connect()->table('comments')->where('status', 'pending')->count('*', 'count')->getValue();
    }


    public function checkFileName(?string $fileName)
    {
        // TODO: Implement checkFileName() method.
    }

}