<?php
declare(strict_types=1);

namespace Celena\Plugin\Shop\Admin;

use Celena\Core\Database\Connection;
use Celena\Core\Http\Pagination;
use Celena\Core\Http\Request;
use Celena\Core\Http\Response;
use Celena\Core\Security\Auth;
use Celena\Core\Security\Csrf;
use Celena\Core\Security\Filter;
use Celena\Core\Template\Engine;
use Celena\Module\AdminBase\AdminController;
use Celena\Module\Settings\Options;

/**
 * Модерация отзывов о товарах. Поддерживается одобрение / снятие
 * одобрения / удаление. После изменений пересчитывается агрегат
 * (rating_avg, rating_count) на shop_products.
 */
final class ReviewsAdminController extends AdminController
{
    private function tr(): \Celena\Core\I18n\Translator
    {
        return \Celena\Core\Kernel::container()->make(\Celena\Core\I18n\Translator::class);
    }

    public function __construct(
        Engine $engine,
        Auth $auth,
        Options $options,
        private readonly Connection $conn,
    ) {
        parent::__construct($engine, $auth, $options);
    }

    public function index(Request $request): Response
    {
        if (!$this->auth->check()) return Response::redirect('/admin/login');
        $tab = (string) $request->query('tab', 'all');
        if (!in_array($tab, ['all', 'pending', 'approved'], true)) $tab = 'all';
        $page = Filter::int($request->query('page', 1), 1);

        $countAll      = $this->conn->builder('shop_reviews')->count();
        $countApproved = $this->conn->builder('shop_reviews')->where('is_approved', '=', true)->count();
        $countPending  = $this->conn->builder('shop_reviews')->where('is_approved', '=', false)->count();

        $countQ = $this->conn->builder('shop_reviews');
        $listQ  = $this->conn->builder('shop_reviews');
        if ($tab === 'pending') {
            $countQ->where('is_approved', '=', false);
            $listQ->where('is_approved', '=', false);
        } elseif ($tab === 'approved') {
            $countQ->where('is_approved', '=', true);
            $listQ->where('is_approved', '=', true);
        }
        $total = $countQ->count();
        $p = new Pagination($page, 25, $total);

        $rows = $listQ->orderBy('created_at', 'desc')->orderBy('id', 'desc')
            ->limit($p->perPage)->offset($p->offset)->get();

        // Подсасываем названия товаров.
        $pids = array_unique(array_map(fn ($r) => (int) $r['product_id'], $rows));
        $titles = [];
        if ($pids !== []) {
            $found = $this->conn->builder('shop_products')->whereIn('id', $pids)->get();
            foreach ($found as $p2) $titles[(int) $p2['id']] = ['title' => (string) $p2['title'], 'slug' => (string) $p2['slug']];
        }
        foreach ($rows as &$r) {
            $r['product_title'] = $titles[(int) $r['product_id']]['title'] ?? '#' . $r['product_id'];
            $r['product_slug']  = $titles[(int) $r['product_id']]['slug']  ?? '';
        }
        unset($r);

        return $this->view('plugins/shop/admin/reviews_index', [
            'reviews'    => $rows,
            'pagination' => $p->toArray('/admin/shop/reviews?tab=' . $tab . '&page=:page'),
            'tab'        => $tab,
            'tab_counts' => ['all' => $countAll, 'approved' => $countApproved, 'pending' => $countPending],
            'total'      => $total,
        ], 'shop-reviews', $this->tr()->translate('shop.reviews_list.title'));
    }

    public function approve(Request $request, array $params): Response
    {
        if (!$this->auth->check()) return Response::redirect('/admin/login');
        if (!Csrf::validate((string) $request->input('_csrf'))) {
            return $this->redirect('/admin/shop/reviews', $this->tr()->translate('shop.flash.csrf'), 'error');
        }
        $id = Filter::int($params['id'] ?? 0);
        $row = $this->conn->builder('shop_reviews')->where('id', '=', $id)->first();
        if ($row === null) return $this->redirect('/admin/shop/reviews', $this->tr()->translate('shop.flash.not_found'), 'error');
        $next = empty($row['is_approved']);
        $this->conn->builder('shop_reviews')->where('id', '=', $id)->update(['is_approved' => $next]);
        $this->recalcRating((int) $row['product_id']);
        return $this->redirect('/admin/shop/reviews', $next ? 'Опубликован.' : 'Снят с публикации.');
    }

    public function delete(Request $request, array $params): Response
    {
        if (!$this->auth->check()) return Response::redirect('/admin/login');
        if (!Csrf::validate((string) $request->input('_csrf'))) {
            return $this->redirect('/admin/shop/reviews', $this->tr()->translate('shop.flash.csrf'), 'error');
        }
        $id = Filter::int($params['id'] ?? 0);
        $row = $this->conn->builder('shop_reviews')->where('id', '=', $id)->first();
        if ($row === null) return $this->redirect('/admin/shop/reviews', $this->tr()->translate('shop.flash.not_found'), 'error');
        $this->conn->builder('shop_reviews')->where('id', '=', $id)->delete();
        $this->recalcRating((int) $row['product_id']);
        return $this->redirect('/admin/shop/reviews', $this->tr()->translate('shop.flash.deleted'));
    }

    private function recalcRating(int $productId): void
    {
        try {
            $sql = 'SELECT COUNT(*) AS c, COALESCE(AVG(' . $this->conn->quoteId('rating') . '),0) AS avg_r '
                . 'FROM ' . $this->conn->table_q('shop_reviews')
                . ' WHERE ' . $this->conn->quoteId('product_id') . ' = ? AND ' . $this->conn->quoteId('is_approved') . ' = ?';
            $row = $this->conn->run($sql, [$productId, true])->fetch();
            $this->conn->builder('shop_products')->where('id', '=', $productId)->update([
                'rating_count' => (int) ($row['c'] ?? 0),
                'rating_avg'   => round((float) ($row['avg_r'] ?? 0), 2),
            ]);
        } catch (\Throwable) {
        }
    }
}
