<?php

use App\Controllers\PublicController;

/**
 * Web Designer task queue. The admin submits a design brief for any page; it
 * lands in cja_tasks as `queued`. The console runner (agents/console/server.mjs)
 * drains the queue: claims the oldest queued row, runs the design agent, builds,
 * and auto-publishes (git commit), then marks it published/failed.
 *
 *   POST /api/admintasks/create   -> { title, target_page, prompt, draft, assets }
 *   GET  /api/admintasks/list     -> [{ task_id, title, status, ... }]
 *   GET  /api/admintasks/get?id=  -> full row + result
 *   POST /api/admintasks/cancel   -> { id }   (only if still queued)
 *
 * All admin-gated. This controller only does CRUD on the queue; the runner owns
 * execution. The Node runner claims/finishes rows via api/cli/tasks-*.php.
 */
class AdminTasks extends PublicController
{
    private const STATUSES = ['queued', 'running', 'published', 'failed', 'canceled'];

    public function create(): void
    {
        $this->requireAdmin();
        $this->guardPublic('admintasks_create', 60, 300);

        $in = json_decode((string) file_get_contents('php://input'), true) ?: [];

        $title  = mb_substr(trim((string) ($in['title'] ?? '')), 0, 200);
        $target = mb_substr(trim((string) ($in['target_page'] ?? '')), 0, 200);
        $prompt = trim((string) ($in['prompt'] ?? ''));
        $draft  = (string) ($in['draft'] ?? '');

        if ($prompt === '') {
            $this->json(null, 400, ['code' => 'no_prompt', 'message' => 'Describe what you want done.']);
        }
        if ($target === '') {
            $this->json(null, 400, ['code' => 'no_target', 'message' => 'Pick a page (or a new page) for the task.']);
        }
        if ($title === '') {
            $title = mb_substr($prompt, 0, 80);
        }

        // Assets: only known-safe local /media/ images and real http(s) video URLs.
        $images = [];
        foreach ((array) ($in['assets']['images'] ?? []) as $img) {
            $url = trim((string) ($img['url'] ?? ''));
            if (preg_match('#^/media/[\w./-]+$#', $url)) {
                $images[] = ['url' => $url, 'alt' => mb_substr(trim((string) ($img['alt'] ?? '')), 0, 200)];
            }
        }
        $videos = [];
        foreach ((array) ($in['assets']['videos'] ?? []) as $v) {
            $url = trim((string) $v);
            if ($url !== '' && filter_var($url, FILTER_VALIDATE_URL) && preg_match('#^https?://#i', $url)) {
                $videos[] = mb_substr($url, 0, 500);
            }
        }
        $assets = json_encode(['images' => $images, 'videos' => $videos], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

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

        $this->json(['ok' => true, 'id' => (int) \Db::getValue('SELECT LAST_INSERT_ID()')]);
    }

    public function list(): void
    {
        $this->requireAdmin();
        $rows = \Db::select(
            'SELECT task_id, title, target_page, status, result, created_at, finished_at
             FROM cja_tasks ORDER BY sort_order DESC, task_id DESC LIMIT 100'
        );
        $out = array_map(function ($r) {
            $result = json_decode($r['result'] ?? '', true) ?: [];
            return [
                'id'      => (int) $r['task_id'],
                'title'   => $r['title'],
                'target'  => $r['target_page'],
                'status'  => $r['status'],
                'commit'  => $result['commit'] ?? '',
                'summary' => $result['summary'] ?? '',
                'live'    => $result['live'] ?? '',
                'error'   => $result['error'] ?? '',
                'created' => $r['created_at'],
                'finished' => $r['finished_at'],
            ];
        }, $rows);
        $this->json(['tasks' => $out]);
    }

    public function get(): void
    {
        $this->requireAdmin();
        $id = (int) ($_GET['id'] ?? 0);
        $r = \Db::getRow('SELECT * FROM cja_tasks WHERE task_id = ?', [$id]);
        if (!$r) {
            $this->json(null, 404, ['code' => 'not_found', 'message' => 'No such task.']);
        }
        $r['assets'] = json_decode($r['assets'] ?? '{}', true) ?: [];
        $r['result'] = json_decode($r['result'] ?? '{}', true) ?: [];
        $this->json($r);
    }

    /** Cancel a task that has not started yet. */
    public function cancel(): void
    {
        $this->requireAdmin();
        $in = json_decode((string) file_get_contents('php://input'), true) ?: [];
        $id = (int) ($in['id'] ?? 0);
        $status = (string) \Db::getValue('SELECT status FROM cja_tasks WHERE task_id = ?', [$id]);
        if ($status === '') {
            $this->json(null, 404, ['code' => 'not_found', 'message' => 'No such task.']);
        }
        if ($status !== 'queued') {
            $this->json(null, 409, ['code' => 'not_queued', 'message' => 'Only queued tasks can be canceled.']);
        }
        \Db::update('cja_tasks', ['status' => 'canceled', 'finished_at' => date('Y-m-d H:i:s')], 'task_id = ?', [$id]);
        $this->json(['ok' => true]);
    }
}
