<?php

use App\Controllers\PublicController;

/**
 * QA reports for the admin. The console runner performs the crawl and writes
 * cja_qa_runs / cja_qa_findings; this controller reads them and, on request,
 * turns a finding into a Web Designer fix task (cja_tasks) — the two queues
 * chain, so a one-click fix flows through the existing build-gated designer.
 *
 *   GET  /api/adminqa/runs                 -> recent runs + counts
 *   GET  /api/adminqa/findings?run=ID      -> findings for a run (default latest)
 *   POST /api/adminqa/fix    { finding_id } -> queue a Web Designer fix task
 *   POST /api/adminqa/ignore { finding_id } -> mark a finding ignored
 *
 * All admin-gated. The QA crawl itself is kicked via POST /devconsole/qa/run.
 */
class AdminQa extends PublicController
{
    public function runs(): void
    {
        $this->requireAdmin();
        $rows = \Db::select(
            'SELECT run_id, status, `trigger`, summary, counts, started_at, finished_at
             FROM cja_qa_runs ORDER BY run_id DESC LIMIT 30'
        );
        $out = array_map(function ($r) {
            return [
                'id'       => (int) $r['run_id'],
                'status'   => $r['status'],
                'trigger'  => $r['trigger'],
                'summary'  => $r['summary'] ?? '',
                'counts'   => json_decode($r['counts'] ?? '{}', true) ?: [],
                'started'  => $r['started_at'],
                'finished' => $r['finished_at'],
            ];
        }, $rows);
        $this->json(['runs' => $out]);
    }

    public function findings(): void
    {
        $this->requireAdmin();
        $runId = (int) ($_GET['run'] ?? 0);
        if ($runId <= 0) {
            $runId = (int) \Db::getValue("SELECT run_id FROM cja_qa_runs WHERE status = 'done' ORDER BY run_id DESC LIMIT 1");
        }
        if ($runId <= 0) { $this->json(['run' => 0, 'findings' => []]); }

        $rows = \Db::select(
            "SELECT finding_id, check_type, severity, url, detail, status
             FROM cja_qa_findings WHERE run_id = ?
             ORDER BY FIELD(severity,'error','warning','info'), check_type, finding_id",
            [$runId]
        );
        $out = array_map(fn($r) => [
            'id'       => (int) $r['finding_id'],
            'check'    => $r['check_type'],
            'severity' => $r['severity'],
            'url'      => $r['url'],
            'detail'   => $r['detail'],
            'status'   => $r['status'],
        ], $rows);
        $this->json(['run' => $runId, 'findings' => $out]);
    }

    /** Turn a finding into a queued Web Designer fix task. */
    public function fix(): void
    {
        $this->requireAdmin();
        $this->guardPublic('adminqa_fix', 60, 300);

        $in = json_decode((string) file_get_contents('php://input'), true) ?: [];
        $fid = (int) ($in['finding_id'] ?? 0);
        $f = \Db::getRow('SELECT * FROM cja_qa_findings WHERE finding_id = ?', [$fid]);
        if (!$f) { $this->json(null, 404, ['code' => 'not_found', 'message' => 'No such finding.']); }
        if ($f['status'] === 'fix_queued') { $this->json(null, 409, ['code' => 'already', 'message' => 'A fix is already queued for this finding.']); }

        // Best-effort target page: a clean root-relative path, else the homepage.
        // The prompt (fix_hint) carries the specific instruction + file/URL.
        $url = (string) $f['url'];
        $target = (str_starts_with($url, '/') && !str_contains($url, ',') && !str_contains($url, '://'))
            ? explode('#', explode('?', $url)[0])[0]
            : '/';
        $prompt = $f['fix_hint'] !== null && $f['fix_hint'] !== ''
            ? (string) $f['fix_hint']
            : "QA found a {$f['check_type']} issue on {$url}: {$f['detail']}. Investigate and fix it.";
        $title = 'QA fix: ' . $f['check_type'] . ' — ' . mb_substr($url, 0, 60);

        $order = (int) \Db::getValue('SELECT COALESCE(MAX(sort_order), 0) + 10 FROM cja_tasks');
        \Db::insert('cja_tasks', [
            'title'       => mb_substr($title, 0, 200),
            'target_page' => mb_substr($target, 0, 200),
            'prompt'      => $prompt,
            'draft'       => '',
            'assets'      => json_encode(['images' => [], 'videos' => []]),
            'status'      => 'queued',
            'sort_order'  => $order,
        ]);
        $taskId = (int) \Db::getValue('SELECT LAST_INSERT_ID()');

        \Db::update('cja_qa_findings', ['status' => 'fix_queued'], 'finding_id = ?', [$fid]);

        // The admin page kicks POST /devconsole/tasks/run after this returns.
        $this->json(['ok' => true, 'task_id' => $taskId]);
    }

    public function ignore(): void
    {
        $this->requireAdmin();
        $in = json_decode((string) file_get_contents('php://input'), true) ?: [];
        $fid = (int) ($in['finding_id'] ?? 0);
        if (!\Db::getValue('SELECT finding_id FROM cja_qa_findings WHERE finding_id = ?', [$fid])) {
            $this->json(null, 404, ['code' => 'not_found', 'message' => 'No such finding.']);
        }
        \Db::update('cja_qa_findings', ['status' => 'ignored'], 'finding_id = ?', [$fid]);
        $this->json(['ok' => true]);
    }
}
