<?php

declare(strict_types=1);



class AdminFeedSourceController
{
    public static function routes(): void
    {
        Router::get('/admin/feeds',            [self::class, 'index']);
        Router::post('/admin/feeds/preview',   [self::class, 'preview']);
        Router::post('/admin/feeds/save',      [self::class, 'save']);
        Router::post('/admin/feeds/delete',    [self::class, 'delete']);
        Router::post('/admin/feeds/toggle',    [self::class, 'toggle']);
        Router::post('/admin/feeds/fetch',     [self::class, 'fetchNow']);
        Router::post('/admin/feeds/run',       [self::class, 'runQueue']);
        Router::post('/admin/feeds/reprocess', [self::class, 'reprocess']);
        Router::post('/admin/feeds/clear-items', [self::class, 'clearItems']);
        Router::get('/admin/feeds/get',        [self::class, 'getOne']);
        Router::get('/admin/feeds/items',      [self::class, 'items']);
        Router::get('/admin/feeds/stats',      [self::class, 'statsJson']);
    }

    public static function index(): void
    {
        Auth::requireAdmin();
         
        Router::redirect('/admin/import?tab=feeds');
    }

     
    public static function preview(): void
    {
        Auth::requireAdmin();
        self::csrfOrFail();
        $url = trim((string) ($_POST['url'] ?? ''));
        if ($url === '') {
            Router::json(['ok' => false, 'error' => 'Enter a feed URL first.']);
        }
        $type      = (string) ($_POST['type'] ?? 'auto');
        $pageParam = trim((string) ($_POST['page_param'] ?? 'page'));
        $res = FeedImportProcessor::preview($url, $type, $pageParam, 1, 24);
        Router::json($res);
    }

    public static function save(): void
    {
        Auth::requireAdmin();
        self::csrfOrFail();

        $id   = (int) ($_POST['id'] ?? 0);
        $name = trim((string) ($_POST['name'] ?? ''));
        $url  = trim((string) ($_POST['url'] ?? ''));
        if ($name === '' || $url === '') {
            Router::json(['ok' => false, 'error' => 'A name and a feed URL are required.']);
        }
        if (!preg_match('#^https?://#i', $url)) {
            Router::json(['ok' => false, 'error' => 'The feed URL must start with http:// or https://']);
        }

        $type  = in_array($_POST['type'] ?? '', ['mrss', 'rss', 'csv', 'json'], true) ? $_POST['type'] : 'mrss';
        $mode  = (($_POST['mode'] ?? 'embed') === 'download') ? 'download' : 'embed';
        $vtype = in_array($_POST['video_type'] ?? '', Video::VALID_TYPES, true) ? $_POST['video_type'] : Video::VALID_TYPES[0];

         
        $mapping = [];
        $rawMap = $_POST['mapping'] ?? [];
        if (is_string($rawMap)) {
            $rawMap = json_decode($rawMap, true) ?: [];
        }
        if (is_array($rawMap)) {
            foreach (FeedParser::CANONICAL_KEYS as $k) {
                $col = trim((string) ($rawMap[$k] ?? ''));
                if ($col !== '') {
                    $mapping[$k] = $col;
                }
            }
        }

        $options = [
            'dedup' => (($_POST['dedup'] ?? 'skip') === 'update') ? 'update' : 'skip',
        ];

        $data = [
            'name'              => mb_substr($name, 0, 150),
            'type'              => $type,
            'url'               => $url,
            'mode'              => $mode,
            'enabled'           => ((int) ($_POST['enabled'] ?? 1)) === 1 ? 1 : 0,
            'auto_publish'      => ((int) ($_POST['auto_publish'] ?? 1)) === 1 ? 1 : 0,
            'video_type'        => $vtype,
            'schedule_interval' => max(0, min(2592000, (int) ($_POST['schedule_interval'] ?? 0))),
            'max_pages'         => max(1, min(50, (int) ($_POST['max_pages'] ?? 1))),
            'page_param'        => mb_substr(trim((string) ($_POST['page_param'] ?? 'page')), 0, 40) ?: 'page',
            'mapping'           => json_encode($mapping),
            'options'           => json_encode($options),
        ];

        if ($id > 0) {
            Database::update('feed_sources', $data, 'id = ?', [$id]);
        } else {
            $id = Database::insert('feed_sources', $data);
        }
        Router::json(['ok' => true, 'id' => $id]);
    }

    public static function getOne(): void
    {
        Auth::requireAdmin();
        $id  = (int) ($_GET['id'] ?? 0);
        $src = Database::fetchOne('SELECT * FROM feed_sources WHERE id = ?', [$id]);
        if (!$src) {
            Router::json(['ok' => false, 'error' => 'Not found'], 404);
        }
        $src['mapping'] = json_decode((string) ($src['mapping'] ?? ''), true) ?: new stdClass();
        $src['options'] = json_decode((string) ($src['options'] ?? ''), true) ?: new stdClass();
        Router::json(['ok' => true, 'source' => $src]);
    }

    public static function delete(): void
    {
        Auth::requireAdmin();
        self::csrfOrFail();
        $id = (int) ($_POST['id'] ?? 0);
        if ($id > 0) {
            Database::query('DELETE FROM feed_sources WHERE id = ?', [$id]);  
        }
        Router::json(['ok' => true]);
    }

    public static function toggle(): void
    {
        Auth::requireAdmin();
        self::csrfOrFail();
        $id = (int) ($_POST['id'] ?? 0);
        Database::query('UPDATE feed_sources SET enabled = 1 - enabled WHERE id = ?', [$id]);
        $row = Database::fetchOne('SELECT enabled FROM feed_sources WHERE id = ?', [$id]);
        Router::json(['ok' => true, 'enabled' => (int) ($row['enabled'] ?? 0)]);
    }

     
    public static function fetchNow(): void
    {
        Auth::requireAdmin();
        self::csrfOrFail();
        $id = (int) ($_POST['id'] ?? 0);
        $src = Database::fetchOne('SELECT id, mode FROM feed_sources WHERE id = ?', [$id]);
        if (!$src) {
            Router::json(['ok' => false, 'error' => 'Source not found'], 404);
        }
        $res = FeedImportProcessor::fetchSource($id);
        $res['processed_now'] = 0;
        if (($src['mode'] ?? '') === 'embed') {
             
            $res['processed_now'] = FeedImportProcessor::processPending($id);
        }
        $res['ok'] = $res['ok'] ?? true;
        Router::json($res);
    }

     
    public static function runQueue(): void
    {
        Auth::requireAdmin();
        self::csrfOrFail();
        $id = (int) ($_POST['id'] ?? 0) ?: null;
        $n = FeedImportProcessor::processPending($id);
        Router::json(['ok' => true, 'processed' => $n]);
    }

    public static function reprocess(): void
    {
        Auth::requireAdmin();
        self::csrfOrFail();
        $id = (int) ($_POST['id'] ?? 0);
        $affected = Database::query(
            "UPDATE feed_items SET status='pending', attempts=0, error='' WHERE source_id = ? AND status='failed'",
            [$id]
        )->rowCount();
        Router::json(['ok' => true, 'requeued' => $affected]);
    }

    public static function clearItems(): void
    {
        Auth::requireAdmin();
        self::csrfOrFail();
        $id = (int) ($_POST['id'] ?? 0);
         
        Database::query('DELETE FROM feed_items WHERE source_id = ?', [$id]);
        Database::query('UPDATE feed_sources SET stat_imported=0, stat_skipped=0, stat_failed=0, stat_fetched=0 WHERE id=?', [$id]);
        Router::json(['ok' => true]);
    }

    public static function items(): void
    {
        Auth::requireAdmin();
        $id = (int) ($_GET['id'] ?? 0);
        $status = $_GET['status'] ?? '';
        $where = 'fi.source_id = ?';
        $params = [$id];
        if (in_array($status, ['pending', 'importing', 'imported', 'skipped', 'failed'], true)) {
            $where .= ' AND fi.status = ?';
            $params[] = $status;
        }
        $rows = Database::fetchAll(
            "SELECT fi.id, fi.guid, fi.title, fi.status, fi.video_id, fi.error, fi.attempts, fi.updated_at,
                    v.slug AS video_slug
             FROM feed_items fi
             LEFT JOIN videos v ON v.id = fi.video_id
             WHERE $where
             ORDER BY fi.id DESC
             LIMIT 200",
            $params
        );
        Router::json(['ok' => true, 'items' => $rows]);
    }

     
    public static function statsJson(): void
    {
        Auth::requireAdmin();
        $id = (int) ($_GET['id'] ?? 0);
        $counts = ['pending' => 0, 'importing' => 0, 'imported' => 0, 'skipped' => 0, 'failed' => 0, 'total' => 0];
        foreach (Database::fetchAll("SELECT status, COUNT(*) c FROM feed_items WHERE source_id = ? GROUP BY status", [$id]) as $r) {
            $counts[$r['status']] = (int) $r['c'];
            $counts['total'] += (int) $r['c'];
        }
        $src = Database::fetchOne('SELECT last_status, last_message, last_run_at, stat_imported, stat_skipped, stat_failed FROM feed_sources WHERE id = ?', [$id]);
        Router::json(['ok' => true, 'counts' => $counts, 'source' => $src]);
    }

    private static function csrfOrFail(): void
    {
        if (!Router::verifyCsrf()) {
            Router::json(['ok' => false, 'error' => 'Invalid CSRF token. Refresh the page and try again.'], 403);
        }
    }
}
