<?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;
use Celena\Plugin\Shop\Support\CustomerRepo;
use Celena\Plugin\Shop\Support\ShopSettings;

/**
 * Раздел «Клиенты». База ведётся автоматически: каждый заказ создаёт/обновляет
 * клиента (см. CheckoutController + OrdersAdminController::storeManual).
 * Здесь — список с поиском, карточка клиента (контакты + история заказов)
 * и ручное редактирование заметки/VIP-флага.
 */
final class CustomersAdminController 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');

        $shop = new ShopSettings($this->options);
        $page = Filter::int($request->query('page', 1), 1);
        $search = trim((string) $request->query('q', ''));
        $tab = (string) $request->query('tab', 'all');
        $sort = (string) $request->query('sort', 'recent');

        $applyFilters = function ($q) use ($search, $tab) {
            if ($search !== '') {
                $like = '%' . mb_strtolower($search, 'UTF-8') . '%';
                $q->whereRaw(
                    '(LOWER(' . $this->conn->quoteId('name') . ') LIKE ? OR '
                    . 'LOWER(' . $this->conn->quoteId('email') . ') LIKE ? OR '
                    . 'LOWER(COALESCE(' . $this->conn->quoteId('phone') . ", '')) LIKE ?)",
                    [$like, $like, $like]
                );
            }
            if ($tab === 'vip')      $q->where('is_vip', '=', true);
            if ($tab === 'repeat')   $q->where('orders_count', '>', 1);
            if ($tab === 'one_time') $q->where('orders_count', '=', 1);
            if ($tab === 'inactive') $q->where('orders_count', '=', 0);
        };

        $sortMap = [
            'recent'   => ['last_order_at', 'desc'],
            'spent'    => ['total_spent', 'desc'],
            'orders'   => ['orders_count', 'desc'],
            'name'     => ['name', 'asc'],
            'newest'   => ['created_at', 'desc'],
        ];
        if (!isset($sortMap[$sort])) $sort = 'recent';

        $countQ = $this->conn->builder('shop_customers');
        $applyFilters($countQ);
        $total = $countQ->count();

        $p = new Pagination($page, 25, $total);

        $listQ = $this->conn->builder('shop_customers');
        $applyFilters($listQ);
        [$col, $dir] = $sortMap[$sort];
        $rows = $listQ->orderBy($col, $dir)->orderBy('id', 'desc')
            ->limit($p->perPage)->offset($p->offset)->get();

        foreach ($rows as &$r) {
            $r['total_spent_fmt'] = $shop->formatPrice((float) ($r['total_spent'] ?? 0));
            $r['last_order_short'] = !empty($r['last_order_at'])
                ? date('d.m.Y', strtotime((string) $r['last_order_at']))
                : '—';
            $r['initials'] = $this->initials((string) ($r['name'] ?? ''), (string) ($r['email'] ?? ''));
        }
        unset($r);

        // Счётчики табов
        $countAll      = (int) $this->conn->builder('shop_customers')->count();
        $countVip      = (int) $this->conn->builder('shop_customers')->where('is_vip', '=', true)->count();
        $countRepeat   = (int) $this->conn->builder('shop_customers')->where('orders_count', '>', 1)->count();
        $countOneTime  = (int) $this->conn->builder('shop_customers')->where('orders_count', '=', 1)->count();
        $countInactive = (int) $this->conn->builder('shop_customers')->where('orders_count', '=', 0)->count();

        $qsParts = [];
        foreach (['q', 'tab', 'sort'] as $k) {
            $v = $request->query($k, '');
            if ($v !== '' && $v !== null) {
                $qsParts[] = rawurlencode($k) . '=' . rawurlencode((string) $v);
            }
        }
        $qs = $qsParts === [] ? '' : ('&' . implode('&', $qsParts));

        return $this->view('plugins/shop/admin/customers_index', [
            'customers'  => $rows,
            'pagination' => $p->toArray('/admin/shop/customers?page=:page' . $qs),
            'q'          => $search,
            'tab'        => $tab,
            'sort'       => $sort,
            'tab_counts' => [
                'all' => $countAll, 'vip' => $countVip, 'repeat' => $countRepeat,
                'one_time' => $countOneTime, 'inactive' => $countInactive,
            ],
            'total' => $total,
        ], 'shop-customers', $this->tr()->translate('shop.customers_list.title'));
    }

    public function show(Request $request, array $params): Response
    {
        if (!$this->auth->check()) return Response::redirect('/admin/login');
        $id = Filter::int($params['id'] ?? 0);
        $row = $this->conn->builder('shop_customers')->where('id', '=', $id)->first();
        if ($row === null) return $this->redirect('/admin/shop/customers', $this->tr()->translate('shop.flash.customer_not_found'), 'error');

        $shop = new ShopSettings($this->options);

        // Все заказы клиента
        $orders = $this->conn->builder('shop_orders')
            ->where('customer_id', '=', $id)
            ->orderBy('created_at', 'desc')
            ->limit(50)
            ->get();
        // Фоллбэк: если customer_id ещё не проставлен (старые заказы) — ищем по email
        if ($orders === [] && !empty($row['email'])) {
            $orders = $this->conn->builder('shop_orders')
                ->whereRaw('LOWER(' . $this->conn->quoteId('customer_email') . ') = ?',
                    [mb_strtolower((string) $row['email'], 'UTF-8')])
                ->orderBy('created_at', 'desc')
                ->limit(50)
                ->get();
        }
        foreach ($orders as &$o) {
            $o['total_fmt'] = $shop->formatPrice((float) ($o['total'] ?? 0));
            $o['date_short'] = !empty($o['created_at'])
                ? date('d.m.Y', strtotime((string) $o['created_at']))
                : '';
        }
        unset($o);

        $row['total_spent_fmt'] = $shop->formatPrice((float) ($row['total_spent'] ?? 0));
        $row['last_order_fmt']  = !empty($row['last_order_at'])
            ? date('d.m.Y H:i', strtotime((string) $row['last_order_at']))
            : '—';
        $row['created_fmt'] = !empty($row['created_at'])
            ? date('d.m.Y', strtotime((string) $row['created_at']))
            : '';
        $row['initials']    = $this->initials((string) ($row['name'] ?? ''), (string) ($row['email'] ?? ''));
        $row['avg_order']   = ((int) ($row['orders_count'] ?? 0)) > 0
            ? $shop->formatPrice((float) $row['total_spent'] / (int) $row['orders_count'])
            : '—';

        return $this->view('plugins/shop/admin/customers_show', [
            'customer' => $row,
            'orders'   => $orders,
        ], 'shop-customers', $row['name'] !== '' ? (string) $row['name'] : (string) $row['email']);
    }

    public function update(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/customers', $this->tr()->translate('shop.flash.csrf'), 'error');
        }
        $id = Filter::int($params['id'] ?? 0);
        $existing = $this->conn->builder('shop_customers')->where('id', '=', $id)->first();
        if ($existing === null) return $this->redirect('/admin/shop/customers', $this->tr()->translate('shop.flash.order_not_found'), 'error');

        $this->conn->builder('shop_customers')->where('id', '=', $id)->update([
            'name'    => Filter::string($request->input('name'), 191),
            'phone'   => Filter::string($request->input('phone'), 32),
            'address' => Filter::string($request->input('address'), 1000),
            'city'    => Filter::string($request->input('city'), 100),
            'country' => Filter::string($request->input('country'), 100),
            'zip'     => Filter::string($request->input('zip'), 20),
            'note'    => Filter::string($request->input('note'), 5000),
            'is_vip'  => Filter::bool($request->input('is_vip')),
            'marketing_opt_in' => Filter::bool($request->input('marketing_opt_in')),
            'updated_at' => date('Y-m-d H:i:s'),
        ]);
        return $this->redirect('/admin/shop/customers/' . $id, $this->tr()->translate('shop.flash.saved'));
    }

    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/customers', $this->tr()->translate('shop.flash.csrf'), 'error');
        }
        $id = Filter::int($params['id'] ?? 0);
        // Заказы не удаляем — просто отвязываем (история продаж важнее).
        $this->conn->builder('shop_orders')
            ->where('customer_id', '=', $id)
            ->update(['customer_id' => null]);
        $this->conn->builder('shop_customers')->where('id', '=', $id)->delete();
        return $this->redirect('/admin/shop/customers', $this->tr()->translate('shop.flash.customer_deleted'));
    }

    /** «Иван Иванов» → «ИИ»; если имени нет — берём первую букву email. */
    private function initials(string $name, string $email): string
    {
        $name = trim($name);
        if ($name !== '') {
            $parts = preg_split('/\s+/u', $name) ?: [];
            $out = '';
            foreach (array_slice($parts, 0, 2) as $p) {
                $out .= mb_strtoupper(mb_substr($p, 0, 1, 'UTF-8'), 'UTF-8');
            }
            return $out !== '' ? $out : '?';
        }
        return $email !== '' ? mb_strtoupper(mb_substr($email, 0, 1, 'UTF-8'), 'UTF-8') : '?';
    }
}
