<?php

declare(strict_types=1);

namespace BotGuard\Controllers\Admin;

use BotGuard\Core\Auth;
use BotGuard\Core\Controller;
use BotGuard\Core\Csrf;
use BotGuard\Core\Request;
use BotGuard\Core\Response;
use BotGuard\Core\Session;
use BotGuard\Core\View;
use BotGuard\Models\Announcement;
use BotGuard\Models\AuditLog;

/**
 * Admin CRUD for dashboard announcements.
 */
final class AnnouncementController extends Controller
{
    public function __construct(
        View $view,
        Session $session,
        Csrf $csrf,
        Request $request,
        private Announcement $announcements,
        private AuditLog $audit,
        private Auth $auth,
    ) {
        parent::__construct($view, $session, $csrf, $request);
    }

    public function index(Request $request): Response
    {
        return $this->render('admin.announcements', [
            'title'         => 'Announcements',
            'announcements' => $this->announcements->all('`id` DESC'),
            'levels'        => Announcement::LEVELS,
        ]);
    }

    public function create(Request $request): Response
    {
        $validator = $this->validate([
            'title' => 'required|maxlen:160',
            'level' => 'required',
        ]);

        if ($validator->fails()) {
            return $this->redirect('/admin/announcements', 'error', $validator->firstError());
        }

        $level = (string) $request->input('level', 'info');
        $level = Announcement::isValidLevel($level) ? $level : 'info';

        $this->announcements->create([
            'title'      => mb_substr((string) $request->input('title'), 0, 160),
            'body'       => mb_substr((string) $request->input('body', ''), 0, 2000),
            'level'      => $level,
            'active'     => 1,
            'starts_at'  => $this->nullableDate($request->input('starts_at')),
            'ends_at'    => $this->nullableDate($request->input('ends_at')),
            'created_by' => $this->auth->id(),
        ]);

        $this->audit->record($this->auth->id(), 'announcement.created', $request->ip(), ['title' => $request->input('title')]);

        return $this->redirect('/admin/announcements', 'success', 'Announcement published.');
    }

    public function toggle(Request $request): Response
    {
        $this->announcements->toggleActive((int) $request->input('id'));

        return $this->redirect('/admin/announcements', 'success', 'Announcement updated.');
    }

    public function delete(Request $request): Response
    {
        $id = (int) $request->input('id');
        $this->announcements->deleteById($id);
        $this->audit->record($this->auth->id(), 'announcement.deleted', $request->ip(), ['id' => $id]);

        return $this->redirect('/admin/announcements', 'success', 'Announcement deleted.');
    }

    private function nullableDate(mixed $value): ?string
    {
        $value = trim((string) $value);
        if ($value === '') {
            return null;
        }

        $ts = strtotime($value);

        return $ts === false ? null : date('Y-m-d H:i:s', $ts);
    }
}
