<?php

use KupShop\AdminBundle\AdminList\BaseList;
use KupShop\AdminBundle\AdminList\FiltersStorage;
use KupShop\AdminBundle\Query\Invert;
use KupShop\CatalogBundle\Util\ReviewsUtil;
use KupShop\KupShopBundle\Util\HtmlBuilder\HTML;
use Query\Operator;

/**
 * Created by PhpStorm.
 * User: hanz
 * Date: 3.6.14
 * Time: 12:30.
 */
class ReviewsList extends BaseList
{
    use FiltersStorage;

    protected $template = 'list/reviews.tpl';
    protected $pageDivide = 200;

    protected $index = -1;
    protected $tableDef = [
        'id' => 'id',
        'fields' => [
            'E-mail' => ['field' => 'email', 'render' => 'renderEmail', 'size' => 0.7],
            'Jméno' => ['field' => 'user_name', 'render' => 'renderObject', 'size' => 0.4, 'visible' => 'N'],
            'Objednávka' => ['field' => 'id_order', 'type' => 'orders', 'type_id' => 'id_order', 'size' => 0.5, 'visible' => 'N'],
            'Produkt' => ['field' => 'product_title', 'type' => 'product', 'type_id' => 'id_product'],
            'Komentář' => ['field' => 'summary', 'render' => 'renderReview', 'size' => 1.7],
            'Datum přidání' => ['field' => 'date', 'render' => 'renderDateTime', 'size' => 0.6],
            'Hodnocení' => ['field' => 'rating', 'render' => 'renderRating', 'size' => 0.5],
            'Ověřená' => ['field' => 'verified', 'spec' => '(r.id_order IS NOT NULL || r.source IS NOT NULL) as verified', 'render' => 'renderVerified', 'size' => 0.4],
            'Stav' => ['field' => 'figure', 'render' => 'renderFigured', 'size' => 0.5, 'class' => 'review-figure'],
            'Top' => ['field' => 'figure', 'render' => 'renderTop', 'class' => 'hiddenTooltip', 'size' => 0.4],
            'Zdroj' => ['field' => 'source', 'render' => 'renderSource', 'size' => 0.5, 'visible' => 'N'],
            'Zamítnout' => ['field' => 'figure', 'render' => 'renderDelete', 'size' => 0.4],
            'Odpověď' => ['field' => 'response', 'size' => 2, 'visible' => 'N'],
        ],
    ];
    protected $orderParam = [
        'sort' => 'Datum přidání',
        'direction' => 'DESC',
    ];

    public function __construct()
    {
        if (!empty($_GET['type_list']) && $_GET['type_list'] == 'showMostRated') {
            $this->tableDef = [
                'id' => 'id',
                'fields' => [
                    'Produkt' => ['field' => 'product_title', 'type' => 'product', 'type_id' => 'id_product'],
                    'Počet hodnocení' => ['field' => 'review'],
                    'Průměrné hodnocení' => ['field' => 'rating', 'render' => 'renderRating'],
                ],
            ];
        }
        if (!empty($_GET['type_list']) && $_GET['type_list'] != 'ShowNotConfirmed' && $_GET['type_list'] != 'ShowConfirmed') {
            unset($this->tableDef['fields']['Top']);
        }
    }

    public function renderEmail($values, $column)
    {
        $value = $this->getListRowValue($values, $column['field']);
        if (empty($value) && ($data = $values['data'])) {
            $data = json_decode($data, true);
            $value = $data['email'] ?? '';
        }

        return $value;
    }

    public function renderVerified($values, $column)
    {
        $value = 'N';
        if (!empty($values['id_order']) || !empty($values['source'])) {
            $value = 'Y';
        }

        return $this->renderBoolean(['verified' => $value], $column);
    }

    public function renderObject($values, $column)
    {
        $value = $this->getListRowValue($values, $column['field']);

        if (empty($value)) {
            return $values['name'];
        } else {
            $output = HTML::create('a');

            $output
                ->attr('href', "javascript:nw('user', '{$values['id_user_name']}')")
                ->text(' $value');
        }
    }

    public function renderRating($values, $column)
    {
        $rating = HTML::create('span');
        for ($i = 0; $i < $values['rating']; $i++) {
            $rating->tag('i')
                ->attr('class', 'glyphicon glyphicon-star rating-full')
                ->end();
        }

        for ($i = 0; $i < intval(5 - $values['rating']); $i++) {
            $rating->tag('i')
                ->attr('class', 'glyphicon glyphicon-star rating-empty')
                ->end();
        }

        return $rating;
    }

    public function renderFigured($values, $column)
    {
        if (array_key_exists($values['figure'], ReviewsUtil::$rank)) {
            return translate(ReviewsUtil::$rank[$values['figure']]);
        }

        return $values['figure'];
    }

    public function renderSource($values, $column)
    {
        return ReviewsUtil::$sources[$values['source']] ?? 'interní';
    }

    public function renderReview($values, $column)
    {
        $output = HTML::create('span');
        if (!empty($values['pros'])) {
            $output
                ->tag('strong')
                    ->text('Pro: ')
                ->end()
                ->text($values['pros'])
                ->tag('br')
                ->end();
        }
        if (!empty($values['cons'])) {
            $output
                ->tag('strong')
                    ->text('Proti: ')
                ->end()
                ->text($values['cons'])
                ->tag('br')
                ->end();
        }
        if (!empty($values['summary'])) {
            $output
                ->tag('strong')
                    ->text('Shrnutí: ')
                ->end()
                ->text($values['summary'])
                ->tag('br')
                ->end();
        }

        return $output;
    }

    public function renderDelete($values, $column)
    {
        return HTML::create('a')
            ->attr('class', 'btn-sm btn btn-danger')
            ->attr('data-form-delete', '')
            ->attr('title', 'Zamítnout hodnocení')
                ->tag('input')
                    ->attr('name', "data[reviews][{$values['id']}][delete]")
                    ->attr('value', '')
                    ->attr('data-form-delete-input', $values['id'])
                    ->attr('type', 'hidden')
                ->end()
                ->tag('span')
                    ->attr('class', 'bi bi-slash-circle')
                ->end();
    }

    public function renderTop($values, $column)
    {
        return HTML::create('a')
            ->attr('class', 'btn-sm btn btn-success review-top'.($values['figure'] == ReviewsUtil::RANK_TOP ? ' disabled' : ''))
            ->attr('data-form-top', '')
            ->attr('title', 'Označit jako TOP (zároveň schválí hodnocení)')
                ->tag('input')
                    ->attr('name', "data[reviews][{$values['id']}][top]")
                    ->attr('value', '')
                    ->attr('data-form-top-input', $values['id'])
                    ->attr('type', 'hidden')
                ->end()
                ->tag('span')
                    ->attr('class', 'bi bi-hand-thumbs-up')
                ->end();
    }

    public function handle()
    {
        parent::handle();

        $data = getVal('data');

        if (!empty($data['reviews'])) {
            foreach ($data['reviews'] as $review_id => $review) {
                if ($review['delete']) {
                    $this->updateSQL('reviews', ['figure' => 0], ['id' => $review_id]);
                } elseif ($review['top']) {
                    $this->updateSQL('reviews', ['figure' => 5], ['id' => $review_id]);
                } elseif (getVal('Submit') == 'Schválit vše') {
                    $this->updateSQL('reviews', ['figure' => 3], ['id' => $review_id]);
                }
            }
        }
    }

    public function getQuery()
    {
        $qb = sqlQueryBuilder()
                ->select('r.*', 'u.id as id_user_name', 'CONCAT(u.name," ", u.surname) as user_name', 'u.email',
                    'CONCAT(p.title, " ", IF(pv.title IS NULL,"", pv.title)) as product_title')
                ->from('reviews', 'r')
                ->leftJoin('r', 'users', 'u', 'r.id_user=u.id')
                ->leftJoin('r', 'products', 'p', 'p.id=r.id_product')
                ->leftJoin('r', 'products_variations', 'pv', 'pv.id=r.id_product_variation');

        if (!empty($_GET['type_list'])) {
            switch ($_GET['type_list']) {
                case 'ShowNotConfirmed':
                    $qb->where('r.figure = 1');
                    break;
                case 'ShowConfirmed':
                    $qb->where('r.figure=3 OR r.figure=5');
                    break;
                case 'showTop':
                    $qb->where('r.figure=5');
                    break;
                case 'showMostRated':
                    $qb = sqlQueryBuilder()
                        ->select('r.id', 'r.id_product', 'COUNT(r.rating) as review', 'AVG(r.rating) as rating', 'CONCAT(p.title, " ", IF(pv.title IS NULL,"", pv.title)) as product_title')
                        ->from('reviews', 'r')
                        ->leftJoin('r', 'products', 'p', 'p.id=r.id_product')
                        ->leftJoin('r', 'products_variations', 'pv', 'pv.id=r.id_product_variation')
                        ->where('r.figure > 1')
                        ->groupBy('r.id_product')
                        ->orderBy('review DESC');

                    $this->orderParam = [
                        'sort' => 'Počet hodnocení',
                        'direction' => 'DESC',
                    ];
                    break;
            }
        } else {
            $review = getVal('review');
            if (!empty($review)) {
                $search = get_search_query(
                    $review,
                    [
                        ['field' => 'r.pros', 'match' => 'both'],
                        ['field' => 'r.cons', 'match' => 'both'],
                        ['field' => 'r.summary', 'match' => 'both'],
                    ]
                );
                $qb->andWhere($search['where']);
                $qb->addParameters($search['data']);
            }

            $email = getVal('email');
            if (!empty($email)) {
                $search = get_search_query(
                    $email,
                    [
                        ['field' => 'u.email', 'match' => 'both'],
                    ]
                );
                $qb->andWhere($search['where']);
                $qb->addParameters($search['data']);
            }

            $dateFrom = getVal('dateFrom');
            $dateTo = getVal('dateTo');
            if (!empty($dateFrom) || !empty($dateTo)) {
                if (!empty($dateFrom)) {
                    $dateFrom = new DateTime($dateFrom);
                    $dateFrom->setTime(0, 0, 0);
                    $qb->andWhere('r.date >= :date_from')->setParameter('date_from', $dateFrom, 'datetime');
                }
                if (!empty($dateTo)) {
                    $dateTo = new DateTime($dateTo);
                    $dateTo->setTime(23, 59, 59);
                    $qb->andWhere('r.date <= :date_to')->setParameter('date_to', $dateTo, 'datetime');
                }
            }

            $figure = getVal('figure');
            $figure_invert = getVal('figure_invert');
            if (isset($figure) && $figure != '') {
                $qb->andWhere(Invert::checkInvert(Operator::inIntArray((array) $figure, 'r.figure'), isset($figure_invert)));
            } else {
                // skip declined reviews by default
                $qb->andWhere('r.figure != 0');
            }

            $ratingFrom = getVal('ratingFrom');
            $ratingTo = getVal('ratingTo');
            if (!empty($ratingFrom) || !empty($ratingTo)) {
                if (!empty($ratingFrom) && intval($ratingFrom)) {
                    $qb->andWhere('r.rating >= :rating_from')->setParameter('rating_from', intval($ratingFrom), 'integer');
                }
                if (!empty($ratingTo) && intval($ratingTo)) {
                    $qb->andWhere('r.rating <= :rating_to')->setParameter('rating_to', intval($ratingTo), 'integer');
                }
            }

            if (!empty($_GET['productId'])) {
                $qb->andWhere(Operator::equals(['r.id_product' => $_GET['productId']]));
                if (!empty($_GET['variationId'])) {
                    $qb->andWhere(Operator::equals(['r.id_product_variation' => $_GET['variationId']]));
                }
            } elseif (!empty($_GET['productId_text'])) {
                $search = get_search_query(
                    $_GET['productId_text'],
                    [
                        ['field' => 'p.title', 'match' => 'both'],
                    ]
                );
                $qb->andWhere($search['where']);
                $qb->addParameters($search['data']);
            }

            $response = getVal('response');
            $response_invert = getVal('response_invert');
            if (!empty(getVal('response'))) {
                array_map(function ($x) use ($qb, $response_invert) {
                    if ($x == 'Y') {
                        $qb->andWhere(Invert::checkInvert(Operator::isNotNull('response'), isset($response_invert)));
                    } elseif ($x == 'N') {
                        $qb->andWhere(Invert::checkInvert(Operator::isNull('response'), isset($response_invert)));
                    }
                }, $response);
            }
        }

        return $qb;
    }
}
