<?php

declare(strict_types=1);

class AdminTagController
{
    public static function routes(): void
    {
        Router::get('/admin/tags', [self::class, 'index']);
        Router::get('/admin/tags/create', [self::class, 'create']);
        Router::post('/admin/tags/store', [self::class, 'store']);
        Router::get('/admin/tags/{id}/edit', [self::class, 'edit']);
        Router::post('/admin/tags/{id}/update', [self::class, 'update']);
        Router::post('/admin/tags/{id}/delete', [self::class, 'destroy']);
        Router::post('/admin/tags/bulk-delete', [self::class, 'bulkDelete']);
        Router::post('/admin/tags/{id}/translations', [self::class, 'saveTranslations']);
        Router::post('/admin/tags/ai-translate-init', [self::class, 'aiTranslateInit']);
        Router::post('/admin/tags/ai-translate-start', [self::class, 'aiTranslateStart']);
        Router::get('/admin/tags/ai-translate-status', [self::class, 'aiTranslateStatus']);
        Router::post('/admin/tags/ai-translate-cancel', [self::class, 'aiTranslateCancel']);
        Router::post('/admin/tags/ai-translate-auto', [self::class, 'aiTranslateAuto']);
    }

    

    public static function aiTranslateAuto(): void
    {
        Auth::requireAdmin();
        if (!Router::verifyCsrf()) { Router::json(['error' => 'Invalid CSRF token'], 403); return; }
        $input = json_decode(file_get_contents('php://input'), true) ?: [];
        $enabled = !empty($input['enabled']) ? '1' : '0';
        Setting::set('entity_autotranslate_tag', $enabled);
        if (Setting::get('entity_autotranslate_category', '0') !== '1' && Setting::get('entity_autotranslate_tag', '0') !== '1') {
            Setting::set('entity_autotranslate_blocked', '0');
            Setting::set('entity_autotranslate_blocked_msg', '');
        }
        Router::json(['success' => true, 'enabled' => $enabled === '1']);
    }

    public static function index(): void
    {
        Auth::requireAdmin();
        $search = $_GET['q'] ?? '';
        $videoFilter = $_GET['videos'] ?? '';
        $sort = $_GET['sort'] ?? 'name';

         
        $typeRows = Database::fetchAll('SELECT video_type, COUNT(*) as cnt FROM tags GROUP BY video_type ORDER BY ' . Video::typeFieldOrder());
        $availableTypes = array_column($typeRows, 'video_type');
        $typeCounts = array_column($typeRows, 'cnt', 'video_type');
        $showTypeFilter = count($availableTypes) > 1;
        $typeFilter = '';
        if ($showTypeFilter) {
            $typeFilter = $_GET['type'] ?? '';
            if ($typeFilter !== '' && !in_array($typeFilter, Video::VALID_TYPES, true)) {
                $typeFilter = '';
            }
        }

        $where = [];
        $params = [];
        if ($search !== '') {
            $where[] = 't.name LIKE ?';
            $params[] = "%{$search}%";
        }
        if ($typeFilter !== '') {
            $where[] = 't.video_type = ?';
            $params[] = $typeFilter;
        }
        $whereClause = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';

        $having = '';
        if ($videoFilter === 'with') $having = 'HAVING video_count > 0';
        elseif ($videoFilter === 'empty') $having = 'HAVING video_count = 0';

        $orderBy = match ($sort) {
            'videos' => 'video_count DESC, t.name ASC',
            'newest' => 't.id DESC',
            default => 't.name ASC',
        };

        $countRow = Database::fetchOne(
            "SELECT COUNT(*) as cnt FROM (
                SELECT t.id, COUNT(vt.video_id) as video_count
                FROM tags t LEFT JOIN video_tags vt ON t.id = vt.tag_id
                {$whereClause}
                GROUP BY t.id {$having}
            ) sub",
            $params
        );
        $total = (int) ($countRow['cnt'] ?? 0);
        $pagination = Pagination::fromRequest($total, 100);

        $tags = Database::fetchAll(
            "SELECT t.*, COUNT(vt.video_id) as video_count
            FROM tags t LEFT JOIN video_tags vt ON t.id = vt.tag_id
            {$whereClause}
            GROUP BY t.id {$having}
            ORDER BY {$orderBy}
            LIMIT ? OFFSET ?",
            array_merge($params, [$pagination->perPage, $pagination->offset])
        );

         
        $tagTranslations = [];
        $tagIds = array_column($tags, 'id');
        if (!empty($tagIds)) {
            $ph = implode(',', array_fill(0, count($tagIds), '?'));
            $tRows = Database::fetchAll(
                "SELECT tag_id, lang_code, name FROM tag_translations WHERE tag_id IN ({$ph}) ORDER BY tag_id, lang_code",
                $tagIds
            );
            foreach ($tRows as $tr) {
                $tagTranslations[(int) $tr['tag_id']][$tr['lang_code']] = $tr['name'];
            }
        }

        Router::render('admin/tags', [
            'pageTitle' => 'Tags', 'activeMenu' => 'tags', 'contentTemplate' => '_tags',
            'headerExtra' => '<button type="button" onclick="AT.translateAll()" class="inline-flex items-center gap-1.5 px-4 py-2 text-sm font-medium text-sky-700 bg-sky-50 hover:bg-sky-100 border border-sky-200 rounded-lg transition-colors"><i class="fa-solid fa-language"></i> Translate All</button>' . (Setting::get('entity_autotranslate_tag', '0') === '1' ? ' <button type="button" onclick="AT.disableAuto()" title="Auto-translation is ON — click to turn off" class="inline-flex items-center gap-1.5 px-3 py-2 text-sm font-medium text-emerald-700 bg-emerald-50 hover:bg-emerald-100 border border-emerald-200 rounded-lg transition-colors"><i class="fa-solid fa-bolt"></i> Auto-translate: ON <i class="fa-solid fa-xmark text-emerald-400"></i></button>' : ''),
            'headerAction' => ['url' => '/admin/tags/create' . ($typeFilter !== '' ? '?type=' . $typeFilter : ''), 'label' => 'New Tag'],
            'tags' => $tags,
            'pagination' => $pagination, 'search' => $search,
            'currentVideoFilter' => $videoFilter,
            'currentSort' => $sort,
            'showTypeFilter' => $showTypeFilter,
            'availableTypes' => $availableTypes,
            'typeCounts' => $typeCounts,
            'currentType' => $typeFilter,
            'tagTranslations' => $tagTranslations,
        ]);
    }

    public static function create(): void
    {
        Auth::requireAdmin();
        Router::render('admin/tag_form', [
            'pageTitle' => 'New Tag', 'activeMenu' => 'tags', 'contentTemplate' => '_tag_form',
            'tag' => null, 'error' => null,
        ]);
    }

    public static function store(): void
    {
        Auth::requireAdmin();
        if (!Router::verifyCsrf()) { Router::redirect('/admin/tags'); }
        $videoType = in_array($_POST['video_type'] ?? '', Video::VALID_TYPES, true) ? $_POST['video_type'] : Video::DEFAULT_TYPE;
        Tag::create([
            'name' => trim($_POST['name'] ?? ''),
            'slug' => Slug::unique('tags', $_POST['name'] ?? '', null, ['video_type' => $videoType]),
            'video_type' => $videoType,
        ]);
        $_SESSION['flash'] = ['type' => 'success', 'message' => 'Tag created successfully.'];
        SitemapController::markDirty();
        Router::redirect('/admin/tags');
    }

    public static function edit(): void
    {
        Auth::requireAdmin();
        $tag = Tag::find((int) Router::param('id'));
        if (!$tag) { Router::redirect('/admin/tags'); }

        $translations = Tag::translations((int) $tag['id']);
        $languages = Translator::available();
        $defaultLang = Translator::getDefaultCode();

        Router::render('admin/tag_form', [
            'pageTitle' => 'Edit Tag', 'activeMenu' => 'tags', 'contentTemplate' => '_tag_form',
            'tag' => $tag, 'error' => null,
            'entityTranslations' => $translations,
            'entityLanguages' => $languages,
            'defaultLang' => $defaultLang,
        ]);
    }

    public static function update(): void
    {
        Auth::requireAdmin();
        if (!Router::verifyCsrf()) { Router::redirect('/admin/tags'); }
        $id = (int) Router::param('id');
        $videoType = in_array($_POST['video_type'] ?? '', Video::VALID_TYPES, true) ? $_POST['video_type'] : Video::DEFAULT_TYPE;
        Tag::update($id, [
            'name' => trim($_POST['name'] ?? ''),
            'slug' => Slug::unique('tags', $_POST['name'] ?? '', $id, ['video_type' => $videoType]),
            'video_type' => $videoType,
        ]);
        $_SESSION['flash'] = ['type' => 'success', 'message' => 'Tag updated successfully.'];
        SitemapController::markDirty();
        Router::redirect('/admin/tags');
    }

    public static function destroy(): void
    {
        Auth::requireAdmin();
        if (!Router::verifyCsrf()) { Router::redirect('/admin/tags'); }
        Tag::delete((int) Router::param('id'));
        $_SESSION['flash'] = ['type' => 'success', 'message' => 'Tag deleted successfully.'];
        SitemapController::markDirty();
        Router::redirect('/admin/tags');
    }

    public static function bulkDelete(): void
    {
        Auth::requireAdmin();
        if (!Router::verifyCsrf()) { http_response_code(403); echo json_encode(['error' => 'CSRF']); return; }
        $input = json_decode(file_get_contents('php://input'), true);
        $ids = array_filter(array_map('intval', $input['ids'] ?? []), fn($id) => $id > 0);
        foreach ($ids as $id) { Tag::delete($id); }
        $_SESSION['flash'] = ['type' => 'success', 'message' => count($ids) . ' tag(s) deleted.'];
        echo json_encode(['deleted' => count($ids)]);
    }

    public static function saveTranslations(): void
    {
        Auth::requireAdmin();
        if (!Router::verifyCsrf()) { Router::json(['error' => 'Invalid CSRF token'], 403); }
        $id = (int) Router::param('id');
        $entity = Tag::find($id);
        if (!$entity) { Router::json(['error' => 'Not found'], 404); }
        $videoType = $entity['video_type'] ?? '';

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

        foreach ($translations as $langCode => $fields) {
            $langCode = preg_replace('/[^a-z]/', '', strtolower($langCode));
            if ($langCode === '' || strlen($langCode) > 5) continue;

            $name = mb_substr(trim($fields['name'] ?? ''), 0, 200);

            if ($name === '') {
                Database::query('DELETE FROM tag_translations WHERE tag_id = ? AND lang_code = ?', [$id, $langCode]);
            } else {
                $slug = Slug::uniqueEntityTranslation('tag_translations', 'tag_id', 'tags', $name, $langCode, $id, $videoType);
                $existing = Database::fetchOne('SELECT id FROM tag_translations WHERE tag_id = ? AND lang_code = ?', [$id, $langCode]);
                if ($existing) {
                    Database::query(
                        'UPDATE tag_translations SET name = ?, slug = ? WHERE tag_id = ? AND lang_code = ?',
                        [$name, $slug, $id, $langCode]
                    );
                } else {
                    Database::query(
                        'INSERT INTO tag_translations (tag_id, lang_code, name, slug) VALUES (?, ?, ?, ?)',
                        [$id, $langCode, $name, $slug]
                    );
                }
            }
        }

        SitemapController::markDirty();
        Router::json(['success' => true]);
    }

    


    private const AI_COST_PER_ENTITY = 0.5;  

    public static function aiTranslateInit(): void
    {
        Auth::requireAdmin();
        if (!Router::verifyCsrf()) { Router::json(['error' => 'CSRF'], 403); return; }
        session_write_close();

        $input = json_decode(file_get_contents('php://input'), true) ?: [];
        $all = !empty($input['all']);
        $skipTranslated = !empty($input['skip_translated']);
        $selectedIds = array_filter(array_map('intval', $input['ids'] ?? []), fn($id) => $id > 0);

         
        $languages = array_values(array_filter(
            Translator::available(),
            fn($l) => !($l['is_default'] ?? false)
        ));

        if (empty($languages)) {
            Router::json(['error' => 'No additional languages enabled. Go to Admin > Languages to enable languages.'], 400);
            return;
        }

        $langCount = count($languages);
        $langCodes = array_column($languages, 'code');

         
        if ($all) {
            $rows = Database::fetchAll('SELECT id, name FROM tags ORDER BY name ASC');
        } else {
            if (empty($selectedIds)) {
                Router::json(['error' => 'No items to translate.'], 400);
                return;
            }
            $ph = implode(',', array_fill(0, count($selectedIds), '?'));
            $rows = Database::fetchAll("SELECT id, name FROM tags WHERE id IN ({$ph})", $selectedIds);
        }

         
        $tooLong = [];
        $validRows = [];
        foreach ($rows as $r) {
            if (mb_strlen($r['name']) > 100) {
                $tooLong[] = $r['name'];
            } else {
                $validRows[] = $r;
            }
        }
        $ids = array_map(fn($r) => (int) $r['id'], $validRows);

        if (empty($ids) && !empty($tooLong)) {
            Router::json(['error' => 'All selected tags exceed 100 characters and cannot be translated.'], 400);
            return;
        }
        if (empty($ids)) {
            Router::json(['error' => 'No items to translate.'], 400);
            return;
        }

         
        $skippedTranslated = 0;
        if ($skipTranslated && !empty($ids)) {
            $ph2 = implode(',', array_fill(0, count($ids), '?'));
            $lph = implode(',', array_fill(0, $langCount, '?'));
            $fullyTranslated = Database::fetchAll(
                "SELECT tag_id FROM tag_translations
                 WHERE tag_id IN ({$ph2}) AND lang_code IN ({$lph}) AND name IS NOT NULL AND name != ''
                 GROUP BY tag_id HAVING COUNT(DISTINCT lang_code) = ?",
                array_merge($ids, $langCodes, [$langCount])
            );
            $fullyDone = array_map(fn($r) => (int) $r['tag_id'], $fullyTranslated);
            if (!empty($fullyDone)) {
                $skippedTranslated = count($fullyDone);
                $ids = array_values(array_diff($ids, $fullyDone));
            }
        }

        $count = count($ids);
        $totalCost = round($count * self::AI_COST_PER_ENTITY, 2);

        $langInfo = array_map(fn($l) => [
            'code' => $l['code'],
            'name' => $l['name'],
            'flag' => Translator::flagCode($l['code']),
        ], $languages);

        $warnings = [];
        if (!empty($tooLong)) {
            $warnings[] = count($tooLong) . ' tag(s) exceed 100 characters and will be skipped: ' . implode(', ', array_map(fn($n) => '"' . mb_strimwidth($n, 0, 30, '...') . '"', array_slice($tooLong, 0, 5)));
        }
        if ($skippedTranslated > 0) {
            $warnings[] = $skippedTranslated . ' tag(s) already fully translated (skipped).';
        }

         
         
        $cachedRate = Setting::get('catalogue_credit_rate', '');
        $creditRate = $cachedRate !== '' ? (float) $cachedRate : 0.01;

         
        if (!CatalogueClient::isConfigured()) {
            Router::json([
                'not_connected' => true,
                'ids'           => $ids,
                'count'         => $count,
                'languages'     => $langInfo,
                'cost_per_item' => self::AI_COST_PER_ENTITY,
                'total_cost'    => $totalCost,
                'credit_rate'   => $creditRate,
                'balance'       => 0,
                'sufficient'    => false,
                'missing'       => $totalCost,
                'warnings'      => $warnings,
            ]);
            return;
        }

        $balance = CatalogueClient::getBalance();
        $credits = (float) ($balance['credits'] ?? 0);
        if (isset($balance['credit_rate']) && (float) $balance['credit_rate'] > 0) {
            $creditRate = (float) $balance['credit_rate'];
        }

        Router::json([
            'ids'           => $ids,
            'count'         => $count,
            'languages'     => $langInfo,
            'cost_per_item' => self::AI_COST_PER_ENTITY,
            'total_cost'    => $totalCost,
            'credit_rate'   => $creditRate,
            'balance'       => $credits,
            'sufficient'    => $credits >= $totalCost,
            'missing'       => $credits >= $totalCost ? 0 : round($totalCost - $credits, 2),
            'warnings'      => $warnings,
        ]);
    }

    public static function aiTranslateStart(): void
    {
        Auth::requireAdmin();
        if (!Router::verifyCsrf()) { Router::json(['error' => 'CSRF'], 403); return; }

         
        $pdo = Database::get();
        $pdo->beginTransaction();
        $existing = $pdo->prepare(
            "SELECT id FROM entity_translate_jobs WHERE entity_type = 'tag' AND status IN ('pending','processing') LIMIT 1 FOR UPDATE"
        );
        $existing->execute();
        if ($existing->fetch()) {
            $pdo->rollBack();
            Router::json(['error' => 'A translation job is already running.'], 409);
            return;
        }
        $pdo->commit();

        $input = json_decode(file_get_contents('php://input'), true) ?: [];
        $ids = array_filter(array_map('intval', $input['ids'] ?? []), fn($id) => $id > 0);

        if (empty($ids)) {
            Router::json(['error' => 'No items to translate.'], 400);
            return;
        }

         
        $languages = array_values(array_filter(
            Translator::available(),
            fn($l) => !($l['is_default'] ?? false)
        ));
        if (empty($languages)) {
            Router::json(['error' => 'No languages enabled.'], 400);
            return;
        }
        $langCodes = array_column($languages, 'code');

         
        $totalCost = round(count($ids) * self::AI_COST_PER_ENTITY, 2);
        $jobId = EntityTranslateProcessor::createJob('tag', $ids, $langCodes, Auth::id(), $totalCost);

        if ($totalCost > 0) {
            $refId = 'entity_translate:tag:job:' . $jobId;
            $debit = CatalogueClient::debitCredits(
                $totalCost,
                'AI translate ' . count($ids) . ' tag(s) (job #' . $jobId . ')',
                $refId
            );
            if ($debit === null || !empty($debit['_error'])) {
                 
                Database::query("DELETE FROM entity_translate_jobs WHERE id = ?", [$jobId]);
                Router::json(['error' => $debit['error'] ?? 'Insufficient credits'], 402);
                return;
            }
        }

        Router::json(['success' => true, 'job_id' => $jobId]);
    }

    public static function aiTranslateStatus(): void
    {
        Auth::requireAdmin();
        session_write_close();

        $jobId = (int) ($_GET['job_id'] ?? 0);
        if ($jobId <= 0) {
             
            $job = EntityTranslateProcessor::getActiveJob('tag');
        } else {
            $job = EntityTranslateProcessor::getJob($jobId);
        }

        if (!$job) {
            Router::json(['active' => false]);
            return;
        }

        Router::json([
            'active'      => in_array($job['status'], ['pending', 'processing'], true),
            'job_id'      => (int) $job['id'],
            'status'      => $job['status'],
            'total'       => (int) $job['total_items'],
            'processed'   => (int) $job['processed_items'],
            'translated'  => (int) $job['translated_count'],
            'failed'      => (int) $job['failed_count'],
            'error'       => $job['error_message'],
            'created_at'  => $job['created_at'],
        ]);
    }

    public static function aiTranslateCancel(): void
    {
        Auth::requireAdmin();
        if (!Router::verifyCsrf()) { Router::json(['error' => 'CSRF'], 403); return; }

        $input = json_decode(file_get_contents('php://input'), true) ?: [];
        $jobId = (int) ($input['job_id'] ?? 0);

        $result = ['success' => true, 'refunded' => 0];
        if ($jobId > 0) {
            $result = EntityTranslateProcessor::cancelJob($jobId, Auth::id());
            if (!empty($result['error'])) {
                Router::json(['error' => $result['error']], 403);
                return;
            }
            $result['success'] = true;
        }

        Router::json($result);
    }
}
