<?php
require_once __DIR__ . '/bootstrap.php';

use CAE\Lib\Response;
use CAE\Lib\View;
use CAE\Lib\Database;
use CAE\Models\Project;
use CAE\Models\Topic;
use CAE\Models\PageType;
use CAE\Models\PromptTemplate;
use CAE\Modules\ContentEngine\ContentGenerator;
use CAE\Modules\ExportEngine\ExportEngine;

$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
$uri    = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
$uri    = '/' . trim(substr($uri, strlen(BASE_URL)), '/');

// Forward API requests to api/index.php
if (str_starts_with($uri, '/api/')) {
    require __DIR__ . '/api/index.php';
    exit;
}

// Support _method override
if ($method === 'POST' && !empty($_POST['_method'])) {
    $method = strtoupper($_POST['_method']);
}

// Helper: redirect with flash
$redirect = function(string $path, string $type, string $msg) {
    View::flash($type, $msg);
    Response::redirect($path);
};

// Sanitize input
$post = function(string $key, mixed $default = ''): mixed {
    return $_POST[$key] ?? $default;
};

// Route match helper
$match = function(string $pattern, string $uri): array|false {
    $regex = '#^' . preg_replace('/\{(\w+)\}/', '(?P<$1>[^/]+)', $pattern) . '$#';
    return preg_match($regex, $uri, $m) ? array_filter($m, 'is_string', ARRAY_FILTER_USE_KEY) : false;
};

try {

    // =========================================================
    // DASHBOARD
    // =========================================================
    if ($method === 'GET' && $uri === '/') {
        $db    = Database::getInstance();
        $stats = [
            'projects'         => $db->count('projects'),
            'topics'           => $db->count('topics'),
            'topics_pending'   => $db->count('topics', "status = 'pending'"),
            'topics_generated' => $db->count('topics', "status = 'generated'"),
            'content_total'    => $db->count('generated_content'),
            'content_approved' => $db->count('generated_content', "status = 'approved'"),
            'content_draft'    => $db->count('generated_content', "status = 'draft'"),
            'content_failed'   => $db->count('generated_content', "status = 'qa_failed'"),
        ];
        $recentContent = $db->fetchAll(
            "SELECT gc.id, gc.status, gc.created_at, t.title, p.business_name, pt.name AS page_type_name, q.word_count
             FROM generated_content gc
             LEFT JOIN topics t ON t.id = gc.topic_id
             LEFT JOIN projects p ON p.id = t.project_id
             LEFT JOIN page_types pt ON pt.id = t.page_type_id
             LEFT JOIN qa_logs q ON q.content_id = gc.id
             ORDER BY gc.created_at DESC LIMIT 5"
        );
        View::render('dashboard', compact('stats', 'recentContent'));
    }

    // =========================================================
    // PROJECTS
    // =========================================================
    elseif ($method === 'GET' && $uri === '/projects') {
        $projects = (new Project())->all();
        View::render('projects/index', compact('projects'));
    }
    elseif ($method === 'GET' && $uri === '/projects/create') {
        View::render('projects/form', ['project' => [], 'action' => BASE_URL . '/projects', 'mode' => 'create']);
    }
    elseif ($method === 'POST' && $uri === '/projects') {
        $p = new Project();
        $id = $p->create([
            'business_name'         => $post('business_name'),
            'website_url'           => $post('website_url'),
            'target_audience'       => $post('target_audience'),
            'content_intent'        => $post('content_intent'),
            'brand_positioning'     => $post('brand_positioning'),
            'tone_voice'            => $post('tone_voice', 'professional'),
            'brand_dos'             => $post('brand_dos'),
            'brand_donts'           => $post('brand_donts'),
            'pov_type'              => $post('pov_type', 'third_person'),
            'seo_philosophy'        => $post('seo_philosophy'),
            'compliance_rules'      => $post('compliance_rules'),
            'brand_reference_style' => $post('brand_reference_style'),
            'cta_style'             => $post('cta_style'),
            'no_no_words'           => $post('no_no_words'),
            'guideline_doc_url'     => $post('guideline_doc_url'),
            'ga4_property_id'       => $post('ga4_property_id'),
            'gsc_site_url'          => $post('gsc_site_url'),
            'gbp_location_id'       => $post('gbp_location_id'),
            'rank_keywords'         => $post('rank_keywords'),
            'rank_competitors'      => $post('rank_competitors'),
            'prompt_queries'        => $post('prompt_queries'),
        ]);
        $redirect('/', 'success', 'Project created successfully!');
    }
    elseif ($method === 'GET' && ($m = $match('/projects/{id}/edit', $uri))) {
        $project = (new Project())->find((int)$m['id']);
        if (!$project) $redirect('/', 'error', 'Project not found');
        View::render('projects/form', ['project' => $project, 'action' => BASE_URL . '/projects/' . $m['id'], 'mode' => 'edit']);
    }
    elseif ($method === 'GET' && ($m = $match('/projects/{id}/research', $uri))) {
        View::render('projects/prompts', ['id' => $m['id'], 'pageTitle' => 'AI Research Prompts']);
    }
    elseif ($method === 'POST' && ($m = $match('/projects/{id}', $uri))) {
        // Build lead_categories JSON from the dynamic row inputs
        $leadCategoriesJson = $post('lead_categories_json');
        if (!$leadCategoriesJson) {
            $keys    = $_POST['lead_cat_key']    ?? [];
            $labels  = $_POST['lead_cat_label']  ?? [];
            $events  = $_POST['lead_cat_events'] ?? [];
            $cpls    = $_POST['lead_cat_cpl']    ?? [];
            $cats    = [];
            foreach ($keys as $i => $key) {
                $key = trim($key);
                if (!$key) continue;
                $evList = array_filter(array_map('trim', explode(',', $events[$i] ?? '')));
                $cats[] = [
                    'key'          => $key,
                    'label'        => trim($labels[$i] ?? $key),
                    'events'       => array_values($evList),
                    'cpl_override' => isset($cpls[$i]) && $cpls[$i] !== '' ? (float)$cpls[$i] : null,
                ];
            }
            $leadCategoriesJson = json_encode($cats);
        }

        (new Project())->update((int)$m['id'], [
            'business_name'         => $post('business_name'),
            'website_url'           => $post('website_url'),
            'target_audience'       => $post('target_audience'),
            'content_intent'        => $post('content_intent'),
            'brand_positioning'     => $post('brand_positioning'),
            'tone_voice'            => $post('tone_voice', 'professional'),
            'brand_dos'             => $post('brand_dos'),
            'brand_donts'           => $post('brand_donts'),
            'pov_type'              => $post('pov_type', 'third_person'),
            'seo_philosophy'        => $post('seo_philosophy'),
            'compliance_rules'      => $post('compliance_rules'),
            'brand_reference_style' => $post('brand_reference_style'),
            'cta_style'             => $post('cta_style'),
            'no_no_words'           => $post('no_no_words'),
            'guideline_doc_url'     => $post('guideline_doc_url'),
            'ga4_property_id'       => $post('ga4_property_id'),
            'gsc_site_url'          => $post('gsc_site_url'),
            'gbp_location_id'       => $post('gbp_location_id'),
            'rank_keywords'         => $post('rank_keywords'),
            'rank_competitors'      => $post('rank_competitors'),
            'prompt_queries'        => $post('prompt_queries'),
            // Analytics config fields
            'business_id'           => $post('business_id'),
            'business_category'     => $post('business_category'),
            'business_sub_category' => $post('business_sub_category'),
            'revenue_managed'       => $post('revenue_managed') !== '' ? (float)$post('revenue_managed') : null,
            'seo_head'              => $post('seo_head'),
            'manager_name'          => $post('manager_name'),
            'sr_analyst'            => $post('sr_analyst'),
            'onboard_date'          => $post('onboard_date') ?: null,
            'brand_term_regex'      => $post('brand_term_regex'),
            'ai_overview_event'     => $post('ai_overview_event'),
            'lead_categories'       => $leadCategoriesJson ?: null,
        ]);
        $redirect('/', 'success', 'Project updated successfully!');
    }
    elseif ($method === 'POST' && ($m = $match('/projects/{id}/delete', $uri))) {
        (new Project())->delete((int)$m['id']);
        $redirect('/', 'success', 'Project deleted.');
    }

    // =========================================================
    // TOPICS
    // =========================================================
    elseif ($method === 'GET' && $uri === '/topics') {
        $projectId = (int)($_GET['project_id'] ?? 0);
        $projects  = (new Project())->all(true);
        $topics    = $projectId ? (new Topic())->allByProject($projectId) : [];
        View::render('topics/index', compact('projects', 'topics', 'projectId'));
    }
    elseif ($method === 'GET' && $uri === '/crawl') {
        Response::redirect(BASE_URL . '/Crawl/public');
    }
    elseif ($method === 'GET' && $uri === '/topics/create') {
        $projects  = (new Project())->all(true);
        $pageTypes = (new PageType())->allForSelect();
        $selProject = (int)($_GET['project_id'] ?? 0);
        View::render('topics/form', ['topic' => null, 'projects' => $projects, 'pageTypes' => $pageTypes, 'selProject' => $selProject, 'mode' => 'create', 'action' => BASE_URL . '/topics']);
    }
    elseif ($method === 'POST' && $uri === '/topics') {
        $id = (new Topic())->create([
            'project_id'          => (int)$post('project_id'),
            'page_type_id'        => (int)$post('page_type_id'),
            'title'               => $post('title'),
            'primary_keyword'     => $post('primary_keyword'),
            'supporting_keywords' => $post('supporting_keywords'),
            'search_intent'       => $post('search_intent', 'informational'),
            'content_angle'       => $post('content_angle'),
            'target_word_count'   => (int)($post('target_word_count') ?: 1200),
            'status'              => 'pending',
        ]);
        $redirect('/topics?project_id=' . $post('project_id'), 'success', 'Topic added successfully!');
    }
    elseif ($method === 'GET' && ($m = $match('/topics/{id}/edit', $uri))) {
        $topic     = (new Topic())->find((int)$m['id']);
        if (!$topic) $redirect('/topics', 'error', 'Topic not found');
        $projects  = (new Project())->all(true);
        $pageTypes = (new PageType())->allForSelect();
        View::render('topics/form', ['topic' => $topic, 'projects' => $projects, 'pageTypes' => $pageTypes, 'selProject' => $topic['project_id'], 'mode' => 'edit', 'action' => BASE_URL . '/topics/' . $m['id']]);
    }
    elseif ($method === 'POST' && ($m = $match('/topics/{id}', $uri))) {
        $t = (new Topic())->find((int)$m['id']);
        (new Topic())->update((int)$m['id'], [
            'project_id'          => (int)$post('project_id'),
            'page_type_id'        => (int)$post('page_type_id'),
            'title'               => $post('title'),
            'primary_keyword'     => $post('primary_keyword'),
            'supporting_keywords' => $post('supporting_keywords'),
            'search_intent'       => $post('search_intent', 'informational'),
            'content_angle'       => $post('content_angle'),
            'target_word_count'   => (int)($post('target_word_count') ?: 1200),
        ]);
        $redirect('/topics?project_id=' . $post('project_id'), 'success', 'Topic updated!');
    }
    elseif ($method === 'POST' && ($m = $match('/topics/{id}/delete', $uri))) {
        $t = (new Topic())->find((int)$m['id']);
        (new Topic())->delete((int)$m['id']);
        $redirect('/topics?project_id=' . ($t['project_id'] ?? ''), 'success', 'Topic deleted.');
    }

    // AI Topic Generator (seed keywords)
    elseif ($method === 'GET' && $uri === '/topics/seed-generate') {
        $projects  = (new Project())->all(true);
        $pageTypes = (new PageType())->allForSelect();
        View::render('topics/seed_generate', compact('projects', 'pageTypes'));
    }

    // Bulk Upload
    elseif ($method === 'GET' && $uri === '/topics/bulk-upload') {
        $projects  = (new Project())->all(true);
        $pageTypes = (new PageType())->allForSelect();
        View::render('topics/bulk_upload', compact('projects', 'pageTypes'));
    }
    elseif ($method === 'POST' && $uri === '/topics/bulk-upload') {
        if (empty($_FILES['csv_file']['tmp_name'])) {
            $redirect('/topics/bulk-upload', 'error', 'Please upload a CSV file');
        }
        $projectId  = (int)$post('project_id');
        $pageTypeId = (int)$post('page_type_id');
        $result     = (new Topic())->parseCSV($_FILES['csv_file']['tmp_name'], $projectId, $pageTypeId);
        if (!empty($result['errors'])) {
            View::flash('warning', 'Uploaded with ' . count($result['errors']) . ' warnings');
        }
        if (!empty($result['rows'])) {
            $count = (new Topic())->bulkCreate($result['rows']);
            $redirect('/topics?project_id=' . $projectId, 'success', "{$count} topics imported successfully!");
        }
        $redirect('/topics/bulk-upload', 'error', 'No valid rows found in CSV');
    }

    // =========================================================
    // CONTENT GENERATION
    // =========================================================
    elseif ($method === 'GET' && $uri === '/content/generate') {
        $projects  = (new Project())->all(true);
        $selProject = (int)($_GET['project_id'] ?? 0);
        $topics     = $selProject ? (new Topic())->pendingByProject($selProject) : [];
        View::render('content/generate', compact('projects', 'selProject', 'topics'));
    }
    elseif ($method === 'POST' && $uri === '/content/generate') {
        $topicIds = array_map('intval', $_POST['topic_ids'] ?? []);
        if (empty($topicIds)) {
            $redirect('/content/generate', 'error', 'Select at least one topic');
        }
        $generator = new ContentGenerator();
        $results   = $generator->generateBatch($topicIds);
        $created   = array_filter($results, fn($r) => !empty($r['content_id']));
        $passed    = array_filter($results, fn($r) => $r['success']);
        $qaFailed  = array_filter($results, fn($r) => !$r['success'] && !empty($r['content_id']));
        $errored   = array_filter($results, fn($r) => empty($r['content_id']));
        if (count($created) > 0) {
            $parts = [];
            if (count($passed))   $parts[] = count($passed)   . ' generated';
            if (count($qaFailed)) $parts[] = count($qaFailed) . ' saved with QA issues';
            if (count($errored))  $parts[] = count($errored)  . ' errors';
            $type = count($passed) > 0 ? 'success' : 'warning';
            $redirect('/content', $type, implode(', ', $parts));
        } else {
            $firstErr = reset($errored);
            $errMsg   = $firstErr['message'] ?? 'Generation failed — check your OpenAI API key and quota';
            $redirect('/content/generate?project_id=' . (int)($_POST['project_id'] ?? 0), 'error', $errMsg);
        }
    }

    // Bulk delete (must come before /content/{id} routes to avoid ID collision)
    elseif ($method === 'POST' && $uri === '/content/bulk-delete') {
        $db  = Database::getInstance();
        $all = !empty($_POST['delete_all']);
        if ($all) {
            $db->query("DELETE FROM generated_content");
            $db->query("DELETE FROM qa_logs");
            $redirect('/content', 'success', 'All content deleted.');
        } else {
            $ids = array_filter(array_map('intval', $_POST['ids'] ?? []));
            if (empty($ids)) {
                $redirect('/content', 'warning', 'No items selected.');
            }
            $ph = implode(',', $ids);
            $db->query("DELETE FROM generated_content WHERE id IN ({$ph})");
            $redirect('/content', 'success', count($ids) . ' item(s) deleted.');
        }
    }

    // =========================================================
    // CONTENT LIBRARY
    // =========================================================
    elseif ($method === 'GET' && $uri === '/content') {
        $db       = Database::getInstance();
        $projects = (new Project())->all(true);
        $selProject = (int)($_GET['project_id'] ?? 0);
        $statusFilter = $_GET['status'] ?? '';

        $whereClause  = '1=1';
        $params       = [];
        if ($selProject) {
            $whereClause .= ' AND t.project_id = ?';
            $params[]     = $selProject;
        }
        if ($statusFilter) {
            $whereClause .= ' AND gc.status = ?';
            $params[]     = $statusFilter;
        }

        $content = $db->fetchAll(
            "SELECT gc.id, gc.status, gc.input_tokens, gc.output_tokens, gc.model_used,
                    gc.generation_time_ms, gc.created_at,
                    t.title, t.primary_keyword, t.project_id,
                    p.business_name, pt.name AS page_type_name,
                    q.word_count, q.passed AS qa_passed, q.keyword_density
             FROM generated_content gc
             LEFT JOIN topics t      ON t.id  = gc.topic_id
             LEFT JOIN projects p    ON p.id  = t.project_id
             LEFT JOIN page_types pt ON pt.id = t.page_type_id
             LEFT JOIN qa_logs q     ON q.content_id = gc.id
             WHERE {$whereClause}
             ORDER BY gc.created_at DESC",
            $params
        );
        View::render('content/library', compact('content', 'projects', 'selProject', 'statusFilter'));
    }
    elseif ($method === 'GET' && ($m = $match('/content/{id}', $uri))) {
        $db   = Database::getInstance();
        $needsMigration = false;
        try {
            $item = $db->fetch(
                "SELECT gc.*, t.title, t.primary_keyword, t.supporting_keywords,
                        t.search_intent, t.content_angle, t.project_id, t.id AS topic_id,
                        p.business_name, p.website_url, pt.name AS page_type_name,
                        q.word_count, q.passed AS qa_passed, q.issues_found, q.checks_detail,
                        q.keyword_density, q.h1_count, q.retry_count,
                        q.readability_score, q.avg_sentence_length, q.paragraph_count, q.unique_word_ratio
                 FROM generated_content gc
                 LEFT JOIN topics t      ON t.id  = gc.topic_id
                 LEFT JOIN projects p    ON p.id  = t.project_id
                 LEFT JOIN page_types pt ON pt.id = t.page_type_id
                 LEFT JOIN qa_logs q     ON q.content_id = gc.id
                 WHERE gc.id = ?
                 ORDER BY q.id DESC LIMIT 1",
                [(int)$m['id']]
            );
        } catch (\PDOException $e) {
            $needsMigration = true;
            $item = $db->fetch(
                "SELECT gc.*, t.title, t.primary_keyword, t.supporting_keywords,
                        t.search_intent, t.content_angle, t.project_id, t.id AS topic_id,
                        p.business_name, p.website_url, pt.name AS page_type_name,
                        q.word_count, q.passed AS qa_passed, q.issues_found,
                        q.keyword_density, q.h1_count, q.retry_count
                 FROM generated_content gc
                 LEFT JOIN topics t      ON t.id  = gc.topic_id
                 LEFT JOIN projects p    ON p.id  = t.project_id
                 LEFT JOIN page_types pt ON pt.id = t.page_type_id
                 LEFT JOIN qa_logs q     ON q.content_id = gc.id
                 WHERE gc.id = ?
                 ORDER BY q.id DESC LIMIT 1",
                [(int)$m['id']]
            );
        }
        if (!$item) $redirect('/content', 'error', 'Content not found');
        foreach (['issues_found', 'checks_detail', 'meta_extras'] as $f) {
            if (!empty($item[$f])) $item[$f] = json_decode($item[$f], true) ?? [];
        }
        $editHistory = [];
        try {
            $editHistory = $db->fetchAll(
                "SELECT id, word_count, edit_note, created_at FROM content_edits WHERE content_id = ? ORDER BY id DESC",
                [(int)$m['id']]
            );
        } catch (\PDOException $ignored) {}
        if ($needsMigration) {
            View::flash('warning', 'Some features require a database migration. Please run <a href="' . BASE_URL . '/migrate.php" target="_blank">migrate.php</a> to enable QA details, SEO metrics, and edit history.');
        }
        View::render('content/view', compact('item', 'editHistory'));
    }
    elseif ($method === 'POST' && ($m = $match('/content/{id}/save-edit', $uri))) {
        $db         = Database::getInstance();
        $id         = (int)$m['id'];
        $newContent = $_POST['content'] ?? '';
        $note       = substr(trim($_POST['note'] ?? ''), 0, 500);

        // Save edit history
        $existing  = $db->fetch("SELECT output FROM generated_content WHERE id = ?", [$id]);
        $wordCount = str_word_count(strip_tags($newContent));
        try {
            $db->insert('content_edits', [
                'content_id'     => $id,
                'content_before' => $existing['output'] ?? '',
                'content_after'  => $newContent,
                'word_count'     => $wordCount,
                'edit_note'      => $note ?: null,
                'created_at'     => date('Y-m-d H:i:s'),
            ]);
        } catch (\PDOException $ignored) {}

        // Run QA on edited content
        $ctx      = $db->fetch(
            "SELECT t.*, p.* FROM generated_content gc
             JOIN topics t   ON t.id = gc.topic_id
             JOIN projects p ON p.id = t.project_id
             WHERE gc.id = ?",
            [$id]
        );
        $qaResult  = $ctx ? (new \CAE\Modules\QAEngine\QAEngine())->check($newContent, $ctx, $ctx) : null;
        $newStatus = ($qaResult && $qaResult['passed']) ? 'draft' : 'qa_failed';

        $db->update('generated_content', [
            'output'     => $newContent,
            'status'     => $newStatus,
            'updated_at' => date('Y-m-d H:i:s'),
        ], 'id = :id', ['id' => $id]);

        // Log QA for this edit
        if ($qaResult) {
            try {
                $db->insert('qa_logs', [
                    'content_id'          => $id,
                    'issues_found'        => json_encode($qaResult['issues']),
                    'checks_detail'       => json_encode($qaResult['checks'] ?? []),
                    'passed'              => $qaResult['passed'] ? 1 : 0,
                    'word_count'          => $qaResult['word_count'],
                    'keyword_density'     => $qaResult['keyword_density'],
                    'readability_score'   => $qaResult['readability_score']   ?? 0,
                    'avg_sentence_length' => $qaResult['avg_sentence_length'] ?? 0,
                    'paragraph_count'     => $qaResult['paragraph_count']     ?? 0,
                    'unique_word_ratio'   => $qaResult['unique_word_ratio']   ?? 0,
                    'h1_count'            => $qaResult['h1_count'],
                    'retry_count'         => 0,
                    'created_at'          => date('Y-m-d H:i:s'),
                ]);
            } catch (\PDOException $ignored) {}
        }

        if (!$qaResult || $qaResult['passed']) {
            $redirect('/content/' . $id, 'success', 'Edit saved. QA passed — ready for approval.');
        } else {
            $issues = implode('; ', array_slice($qaResult['issues'], 0, 3));
            $redirect('/content/' . $id, 'warning', 'Edit saved with QA issues: ' . $issues . '. Use the Approve button to override manually.');
        }
    }
    elseif ($method === 'POST' && ($m = $match('/content/{id}/approve', $uri))) {
        $db = Database::getInstance();
        $db->update('generated_content', ['status' => 'approved', 'updated_at' => date('Y-m-d H:i:s')], 'id = :id', ['id' => (int)$m['id']]);
        $redirect('/content/' . $m['id'], 'success', 'Content approved!');
    }
    elseif ($method === 'POST' && ($m = $match('/content/{id}/delete', $uri))) {
        Database::getInstance()->delete('generated_content', 'id = ?', [(int)$m['id']]);
        $redirect('/content', 'success', 'Content deleted.');
    }
    elseif ($method === 'POST' && ($m = $match('/content/{id}/regenerate', $uri))) {
        $db  = Database::getInstance();
        $id  = (int)$m['id'];
        $row = $db->fetch("SELECT topic_id FROM generated_content WHERE id = ?", [$id]);
        if (!$row) $redirect('/content', 'error', 'Content not found');
        $topicId = (int)$row['topic_id'];
        $db->delete('generated_content', 'id = ?', [$id]);
        $db->update('topics', ['status' => 'pending', 'updated_at' => date('Y-m-d H:i:s')], 'id = :id', ['id' => $topicId]);
        set_time_limit(300);
        $result = (new ContentGenerator())->generate($topicId);
        if (!empty($result['content_id'])) {
            $msg = $result['success'] ? 'Content regenerated successfully.' : 'Regenerated — QA issues remain. Review before approving.';
            $redirect('/content/' . $result['content_id'], $result['success'] ? 'success' : 'warning', $msg);
        } else {
            $redirect('/content', 'error', $result['message'] ?? 'Regeneration failed');
        }
    }

    // Export
    elseif ($method === 'GET' && ($m = $match('/content/{id}/export/{format}', $uri))) {
        $exp    = new ExportEngine();
        $id     = (int)$m['id'];
        $format = strtolower($m['format']);
        switch ($format) {
            case 'html':
                Response::download($exp->toHTML($id), "content-{$id}.html", 'text/html');
                break;
            case 'json':
                Response::download($exp->toJSON($id), "content-{$id}.json", 'application/json');
                break;
            case 'word':
                Response::download($exp->toWord($id), "content-{$id}.doc", 'application/msword');
                break;
            default:
                $redirect('/content/' . $id, 'error', 'Invalid export format');
        }
    }

    // =========================================================
    // PROMPT TEMPLATES
    // =========================================================
    elseif ($method === 'GET' && $uri === '/templates') {
        $templates = (new PromptTemplate())->all();
        $pageTypes = (new PageType())->allForSelect();
        View::render('prompt_templates/index', compact('templates', 'pageTypes'));
    }
    elseif ($method === 'GET' && $uri === '/templates/create') {
        $pageTypes = (new PageType())->allForSelect();
        View::render('prompt_templates/form', ['template' => null, 'pageTypes' => $pageTypes, 'mode' => 'create', 'action' => BASE_URL . '/templates']);
    }
    elseif ($method === 'POST' && $uri === '/templates') {
        $id = (new PromptTemplate())->create([
            'page_type_id'  => (int)$post('page_type_id'),
            'name'          => $post('name'),
            'system_prompt' => $post('system_prompt'),
            'user_prompt'   => $post('user_prompt'),
            'version'       => $post('version', '1.0'),
            'is_active'     => (int)(bool)$post('is_active'),
        ]);
        $redirect('/templates', 'success', 'Template created!');
    }
    elseif ($method === 'GET' && ($m = $match('/templates/{id}/edit', $uri))) {
        $template  = (new PromptTemplate())->find((int)$m['id']);
        if (!$template) $redirect('/templates', 'error', 'Template not found');
        $pageTypes = (new PageType())->allForSelect();
        View::render('prompt_templates/form', ['template' => $template, 'pageTypes' => $pageTypes, 'mode' => 'edit', 'action' => BASE_URL . '/templates/' . $m['id']]);
    }
    elseif ($method === 'POST' && ($m = $match('/templates/{id}', $uri))) {
        (new PromptTemplate())->update((int)$m['id'], [
            'page_type_id'  => (int)$post('page_type_id'),
            'name'          => $post('name'),
            'system_prompt' => $post('system_prompt'),
            'user_prompt'   => $post('user_prompt'),
            'version'       => $post('version', '1.0'),
            'is_active'     => (int)(bool)$post('is_active'),
        ]);
        $redirect('/templates', 'success', 'Template updated!');
    }
    elseif ($method === 'POST' && ($m = $match('/templates/{id}/delete', $uri))) {
        (new PromptTemplate())->delete((int)$m['id']);
        $redirect('/templates', 'success', 'Template deleted.');
    }

    // =========================================================
    // RESEARCH
    // =========================================================
    elseif ($method === 'GET' && $uri === '/research') {
        View::render('research/index', ['pageTitle' => 'AI Prompt Research']);
    }
    elseif ($method === 'GET' && $uri === '/research/details') {
        View::render('research/details', ['id' => $_GET['id'] ?? 0]);
    }

    // =========================================================
    // PAGE TYPES
    // =========================================================
    elseif ($method === 'GET' && $uri === '/page-types') {
        $pageTypes = (new PageType())->all();
        View::render('page_types/index', compact('pageTypes'));
    }

    elseif ($uri === '/image-optimization') {
        View::render('image_optimization/index', ['pageTitle' => 'Image Optimization']);
    }

    // =========================================================
    // 404
    // =========================================================
    else {
        http_response_code(404);
        View::render('errors/404');
    }

} catch (\Exception $e) {
    if (($_ENV['APP_DEBUG'] ?? true)) {
        echo '<pre style="background:#1e1e2e;color:#cdd6f4;padding:20px;font-family:monospace;">';
        echo '<b style="color:#f38ba8">Error:</b> ' . htmlspecialchars($e->getMessage()) . "\n\n";
        echo htmlspecialchars($e->getTraceAsString());
        echo '</pre>';
    } else {
        http_response_code(500);
        View::render('errors/500');
    }
}
