<?php
declare(strict_types=1);

namespace Celena\Plugin\Shop\Controllers;

use Celena\Core\Http\Flash;
use Celena\Core\Http\Request;
use Celena\Core\Http\Response;
use Celena\Core\Security\Csrf;
use Celena\Core\Security\Filter;
use Celena\Module\Account\AccountBaseController;
use Celena\Module\Account\AccountTabs;
use Celena\Plugin\Shop\Support\CustomerRepo;
use Celena\Plugin\Shop\Support\ShopSettings;

/**
 * Подстраницы личного кабинета, добавляемые магазином: Заказы, Избранное, Адреса.
 * Расширяет ядровый AccountBaseController (рендер в активной теме + общий каркас).
 * Доступ — через ту же CustomerAuthMiddleware (см. plugin.php), что и ядровый кабинет.
 *
 * Ничего в ядре не меняется: вкладки добавляются фильтром account.tabs,
 * заказы привязаны к user_id (см. account.authenticated в plugin.php).
 */
final class AccountController extends AccountBaseController
{
    private const STATUS = [
        'new'       => 'Новый',
        'paid'      => 'Оплачен',
        'shipped'   => 'Отправлен',
        'delivered' => 'Доставлен',
        'cancelled' => 'Отменён',
    ];

    public function orders(Request $request): Response
    {
        $uid = (int) $this->auth->id();
        $rows = $this->conn->builder('shop_orders')
            ->where('user_id', '=', $uid)
            ->orderBy('created_at', 'desc')
            ->limit(100)
            ->get();
        $orders = array_map([$this, 'decorateOrder'], $rows);

        return $this->renderAccount('plugins/shop/account/orders', [
            'orders'       => $orders,
            'orders_empty' => $orders === [] ? '1' : '0',
        ], 'Мои заказы', 'orders');
    }

    public function order(Request $request, array $params): Response
    {
        $number = (string) ($params['number'] ?? '');
        $uid = (int) $this->auth->id();
        $order = $this->conn->builder('shop_orders')
            ->where('number', '=', $number)
            ->where('user_id', '=', $uid)
            ->first();
        if ($order === null) {
            Flash::error('Заказ не найден.');
            return Response::redirect('/account/orders');
        }
        $items = $this->conn->builder('shop_order_items')
            ->where('order_id', '=', (int) $order['id'])
            ->get();

        return $this->renderAccount('plugins/shop/account/order', [
            'order' => $this->decorateOrder($order),
            'items' => $items,
        ], 'Заказ ' . $number, 'orders');
    }

    public function favorites(Request $request): Response
    {
        // Список избранного хранится в localStorage (celena_shop_favorites) —
        // оболочку наполняет JS, подтягивая товары через /account/favorites/items.
        return $this->renderAccount('plugins/shop/account/favorites', [], 'Избранное', 'favorites');
    }

    /** JSON: товары по списку id (для рендера избранного из localStorage). */
    public function favoritesItems(Request $request): Response
    {
        $ids = array_values(array_filter(array_map(
            'intval',
            explode(',', (string) $request->query('ids', ''))
        )));
        if ($ids === []) {
            return Response::json([]);
        }
        $ids = array_slice($ids, 0, 60);
        $rows = $this->conn->builder('shop_products')
            ->whereIn('id', $ids)
            ->where('is_active', '=', true)
            ->get();

        $shop = new ShopSettings($this->options);
        $out = [];
        foreach ($rows as $p) {
            $out[] = [
                'id'        => (int) $p['id'],
                'title'     => (string) $p['title'],
                'url'       => '/shop/product/' . (string) $p['slug'],
                'cover'     => (string) ($p['cover'] ?? ''),
                'price_fmt' => $shop->formatPrice((float) ($p['price'] ?? 0)),
            ];
        }
        return Response::json($out);
    }

    public function addresses(Request $request): Response
    {
        return $this->renderAccount('plugins/shop/account/addresses', [
            'cust' => $this->currentCustomer(),
        ], 'Адреса и контакты', 'addresses');
    }

    public function saveAddresses(Request $request): Response
    {
        if (!Csrf::validate((string) $request->input('_csrf'))) {
            Flash::error('Сессия устарела, попробуйте ещё раз.');
            return Response::redirect('/account/addresses');
        }
        $user = $this->auth->user();
        if ($user === null || empty($user['email'])) {
            return Response::redirect('/account/login');
        }
        (new CustomerRepo($this->conn))->upsertFromOrder([
            'email'   => (string) $user['email'],
            'user_id' => (int) $user['id'],
            '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),
        ]);
        Flash::success('Контактные данные сохранены.');
        return Response::redirect('/account/addresses');
    }

    /**
     * @param array<string, mixed> $vars
     */
    private function renderAccount(string $template, array $vars, string $title, string $active): Response
    {
        $vars['account_tabs'] = AccountTabs::build($this->auth->user(), $active);
        $vars['account_active'] = $active;
        return $this->render($template, $vars, $title);
    }

    /**
     * @param array<string, mixed> $o
     * @return array<string, mixed>
     */
    private function decorateOrder(array $o): array
    {
        $status = (string) ($o['status'] ?? 'new');
        $o['status_label'] = self::STATUS[$status] ?? $status;
        $created = (string) ($o['created_at'] ?? '');
        $ts = $created !== '' ? strtotime($created) : false;
        $o['date_fmt'] = $ts !== false ? date('d.m.Y', $ts) : $created;
        return $o;
    }

    /** @return array<string, mixed> Текущая карточка клиента (shop_customers) или пустой массив. */
    private function currentCustomer(): array
    {
        $user = $this->auth->user() ?? [];
        $row = $this->conn->builder('shop_customers')
            ->where('user_id', '=', (int) ($user['id'] ?? 0))
            ->first();
        if ($row === null && !empty($user['email'])) {
            $row = $this->conn->builder('shop_customers')
                ->where('email', '=', mb_strtolower((string) $user['email'], 'UTF-8'))
                ->first();
        }
        return $row ?? [];
    }
}
