<?php
declare(strict_types=1);

namespace Celena\Module\Banners;

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;

/**
 * Баннеры — изображения для слайдеров и промо-зон сайта.
 * Тема использует их через тег [banners placement="hero"] (план).
 * Размещения: hero | sidebar | footer | popup. При окончании ends_at
 * баннер автоматически снимается с показа.
 */
final class BannersController extends AdminController
{
    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 ($deny = $this->deny('banners.manage')) return $deny;
        $page = Filter::int($request->query('page', 1), 1);
        $placement = (string) $request->query('placement', '');

        $countQ = $this->conn->builder('celena_banners');
        $listQ  = $this->conn->builder('celena_banners');
        if ($placement !== '') {
            $countQ->where('placement', '=', $placement);
            $listQ->where('placement', '=', $placement);
        }
        $total = $countQ->count();
        $p = new Pagination($page, 25, $total);

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

        return $this->view('admin/banners/index', [
            'banners'   => $rows,
            'pagination'=> $p->toArray('/admin/banners?page=:page' . ($placement !== '' ? '&placement=' . rawurlencode($placement) : '')),
            'placement' => $placement,
            'total'     => $total,
        ], 'banners', 'Баннеры');
    }

    public function create(Request $request): Response
    {
        if ($deny = $this->deny('banners.manage')) return $deny;
        return $this->view('admin/banners/form', [
            'row' => $this->emptyRow(),
            'form_action' => '/admin/banners/create',
        ], 'banners', 'Новый баннер');
    }

    public function store(Request $request): Response
    {
        if ($deny = $this->deny('banners.manage')) return $deny;
        if (!Csrf::validate((string) $request->input('_csrf'))) {
            return $this->redirect('/admin/banners/create', 'CSRF.', 'error');
        }
        $data = $this->extract($request);
        if ($data['title'] === '') {
            return $this->redirect('/admin/banners/create', 'Заголовок обязателен.', 'error');
        }
        $now = date('Y-m-d H:i:s');
        $data['created_at'] = $now;
        $data['updated_at'] = $now;
        $this->conn->builder('celena_banners')->insert($data);
        return $this->redirect('/admin/banners', 'Баннер создан.');
    }

    public function edit(Request $request, array $params): Response
    {
        if ($deny = $this->deny('banners.manage')) return $deny;
        $id = Filter::int($params['id'] ?? 0);
        $row = $this->conn->builder('celena_banners')->where('id', '=', $id)->first();
        if ($row === null) return $this->redirect('/admin/banners', 'Не найден.', 'error');
        return $this->view('admin/banners/form', [
            'row' => $row,
            'form_action' => '/admin/banners/' . $id . '/update',
        ], 'banners', 'Баннер: ' . $row['title']);
    }

    public function update(Request $request, array $params): Response
    {
        if ($deny = $this->deny('banners.manage')) return $deny;
        if (!Csrf::validate((string) $request->input('_csrf'))) {
            return $this->redirect('/admin/banners', 'CSRF.', 'error');
        }
        $id = Filter::int($params['id'] ?? 0);
        $existing = $this->conn->builder('celena_banners')->where('id', '=', $id)->first();
        if ($existing === null) return $this->redirect('/admin/banners', 'Не найден.', 'error');
        $data = $this->extract($request);
        $data['updated_at'] = date('Y-m-d H:i:s');
        $this->conn->builder('celena_banners')->where('id', '=', $id)->update($data);
        return $this->redirect('/admin/banners', 'Сохранено.');
    }

    public function delete(Request $request, array $params): Response
    {
        if ($deny = $this->deny('banners.manage')) return $deny;
        if (!Csrf::validate((string) $request->input('_csrf'))) {
            return $this->redirect('/admin/banners', 'CSRF.', 'error');
        }
        $id = Filter::int($params['id'] ?? 0);
        $this->conn->builder('celena_banners')->where('id', '=', $id)->delete();
        return $this->redirect('/admin/banners', 'Удалено.');
    }

    private function emptyRow(): array
    {
        return [
            'id' => 0, 'title' => '', 'image' => '', 'mobile_image' => '', 'url' => '',
            'placement' => 'hero', 'subtitle' => '', 'cta_label' => '',
            'starts_at' => '', 'ends_at' => '',
            'sort_order' => 0, 'is_active' => true,
        ];
    }

    private function extract(Request $request): array
    {
        $placement = (string) $request->input('placement', 'hero');
        if (!in_array($placement, ['hero', 'sidebar', 'footer', 'popup'], true)) {
            $placement = 'hero';
        }
        $startsAt = (string) $request->input('starts_at', '');
        $endsAt   = (string) $request->input('ends_at', '');
        return [
            'title'        => Filter::string($request->input('title'), 255),
            'image'        => Filter::string($request->input('image'), 500),
            'mobile_image' => Filter::string($request->input('mobile_image'), 500),
            'url'          => Filter::string($request->input('url'), 500),
            'placement'    => $placement,
            'subtitle'     => Filter::string($request->input('subtitle'), 1000),
            'cta_label'    => Filter::string($request->input('cta_label'), 100),
            'starts_at'    => $startsAt === '' ? null : $startsAt,
            'ends_at'      => $endsAt === '' ? null : $endsAt,
            'sort_order'   => Filter::int($request->input('sort_order'), 0),
            'is_active'    => Filter::bool($request->input('is_active')),
        ];
    }
}
