<?php

declare(strict_types=1);

namespace BotGuard\Controllers\User;

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\VerificationResult;
use BotGuard\Services\Export\CsvExporter;
use BotGuard\Services\Export\PdfReportExporter;
use BotGuard\Services\Export\XlsxExporter;

/**
 * User dashboard: verification statistics, analytics, logs, reports and CSV
 * export. Data is scoped to the authenticated user (admins see all traffic).
 */
final class DashboardController extends Controller
{
    public function __construct(
        View $view,
        Session $session,
        Csrf $csrf,
        Request $request,
        private Auth $auth,
        private VerificationResult $results,
        private CsvExporter $csv,
        private XlsxExporter $xlsx,
        private PdfReportExporter $pdf,
        private Announcement $announcements,
    ) {
        parent::__construct($view, $session, $csrf, $request);
    }

    /** Column layout shared by every export format. */
    private const EXPORT_HEADERS = ['Time', 'IP', 'Country', 'Browser', 'OS', 'Device', 'Score', 'Class', 'Decision', 'CAPTCHA'];

    /**
     * Flatten result rows to the export column order.
     *
     * @param array<int, array<string, mixed>> $rows
     * @return array<int, array<int, string>>
     */
    private function exportRows(array $rows): array
    {
        return array_map(static fn (array $r): array => [
            (string) $r['created_at'], (string) $r['ip'], (string) ($r['country'] ?? ''),
            (string) ($r['browser'] ?? ''), (string) ($r['os'] ?? ''), (string) ($r['device_type'] ?? ''),
            (string) $r['score'], (string) $r['classification'], (string) $r['decision'],
            (string) ($r['captcha_result'] ?? ''),
        ], $rows);
    }

    /**
     * Admins see global traffic; regular users see only their own.
     */
    private function scopeUserId(): ?int
    {
        return $this->auth->isAdmin() ? null : $this->auth->id();
    }

    public function index(Request $request): Response
    {
        $userId = $this->scopeUserId();

        return $this->render('user.dashboard', [
            'title'         => 'Dashboard',
            'announcements' => $this->announcements->activeNow(),
            'summary'   => $this->results->summary($userId),
            'trend'     => $this->results->dailyTrend($userId, 14),
            'browsers'  => $this->results->topBy('browser', $userId),
            'devices'   => $this->results->topBy('device_type', $userId),
            'countries' => $this->results->topBy('country', $userId),
            'recent'    => $this->results->recent($userId, 10),
        ]);
    }

    public function analytics(Request $request): Response
    {
        $userId = $this->scopeUserId();

        return $this->render('user.analytics', [
            'title'     => 'Analytics',
            'summary'   => $this->results->summary($userId),
            'trend'     => $this->results->dailyTrend($userId, 30),
            'browsers'  => $this->results->topBy('browser', $userId, 8),
            'os'        => $this->results->topBy('os', $userId, 8),
            'devices'   => $this->results->topBy('device_type', $userId),
            'countries' => $this->results->topBy('country', $userId, 8),
            'referrers' => $this->results->topBy('referrer_type', $userId),
        ]);
    }

    public function logs(Request $request): Response
    {
        return $this->render('user.logs', [
            'title'   => 'Detection Logs',
            'results' => $this->results->recent($this->scopeUserId(), 100),
        ]);
    }

    public function reports(Request $request): Response
    {
        $userId = $this->scopeUserId();

        return $this->render('user.reports', [
            'title'   => 'Risk Reports',
            'summary' => $this->results->summary($userId),
            'trend'   => $this->results->dailyTrend($userId, 30),
        ]);
    }

    public function exportCsv(Request $request): Response
    {
        $rows = $this->exportRows($this->results->recent($this->scopeUserId(), 5000));

        return $this->csv->download('verifications-' . date('Ymd-His') . '.csv', self::EXPORT_HEADERS, $rows);
    }

    public function exportXlsx(Request $request): Response
    {
        $rows = $this->exportRows($this->results->recent($this->scopeUserId(), 5000));

        return $this->xlsx->download('verifications-' . date('Ymd-His') . '.xlsx', self::EXPORT_HEADERS, $rows, 'Verifications');
    }

    public function exportPdf(Request $request): Response
    {
        $userId = $this->scopeUserId();
        $summary = $this->results->summary($userId);
        $rows = $this->exportRows($this->results->recent($userId, 1000));

        // Column widths (points) sized for A4 portrait (~515pt usable).
        $columns = [
            ['label' => 'Time', 'width' => 95], ['label' => 'IP', 'width' => 80],
            ['label' => 'Country', 'width' => 45], ['label' => 'Browser', 'width' => 70],
            ['label' => 'OS', 'width' => 70], ['label' => 'Device', 'width' => 45],
            ['label' => 'Score', 'width' => 35], ['label' => 'Class', 'width' => 75],
        ];
        // PDF is a summary view: drop the last two verbose columns for readability.
        $pdfRows = array_map(static fn (array $r): array => array_slice($r, 0, 8), $rows);

        return $this->pdf->report(
            'verification-report-' . date('Ymd-His') . '.pdf',
            'Verification Report',
            [
                'Total'      => (int) ($summary['total'] ?? 0),
                'Humans'     => (int) ($summary['humans'] ?? 0),
                'Suspicious' => (int) ($summary['suspicious'] ?? 0),
                'Bots'       => (int) ($summary['bots'] ?? 0),
                'Avg Score'  => (float) ($summary['avg_score'] ?? 0),
            ],
            $columns,
            $pdfRows
        );
    }
}
