<?php

declare(strict_types=1);

require_once dirname(__DIR__) . '/config/php-guard.php';  
require_once dirname(__DIR__) . '/config/app.php';

 
if (!App::isInstalled()) {
    $reqPath = rtrim(parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?? '/', '/') ?: '/';
    if ($reqPath !== '/install' && !str_starts_with($reqPath, '/install/')) {
        Router::redirect('/install');
    }
    require_once APP_ROOT . '/src/Install/InstallController.php';
    InstallController::routes();
    Router::dispatch();
    exit;
}

 
require_once APP_ROOT . '/config/database.php';

 
 
 
UpdateManager::ensureSchema();

 
require_once APP_ROOT . '/src/Admin/AdminController.php';
require_once APP_ROOT . '/src/Admin/VideoController.php';
require_once APP_ROOT . '/src/Admin/AlbumController.php';
require_once APP_ROOT . '/src/Admin/AlbumCategoryController.php';
require_once APP_ROOT . '/src/Admin/AlbumTagController.php';
require_once APP_ROOT . '/src/Admin/AlbumPerformerController.php';
require_once APP_ROOT . '/src/Admin/AlbumChannelController.php';
require_once APP_ROOT . '/src/Admin/CategoryController.php';
require_once APP_ROOT . '/src/Admin/TagController.php';
require_once APP_ROOT . '/src/Admin/PerformerController.php';
require_once APP_ROOT . '/src/Admin/UserController.php';
require_once APP_ROOT . '/src/Admin/CommentController.php';
require_once APP_ROOT . '/src/Admin/PageController.php';
require_once APP_ROOT . '/src/Admin/SettingController.php';
require_once APP_ROOT . '/src/Admin/PluginController.php';
require_once APP_ROOT . '/src/Admin/ThemeController.php';
require_once APP_ROOT . '/src/Admin/ChannelController.php';
require_once APP_ROOT . '/src/Admin/LanguageController.php';
require_once APP_ROOT . '/src/Admin/ImportController.php';
require_once APP_ROOT . '/src/Admin/FeedSourceController.php';
require_once APP_ROOT . '/src/Admin/CatalogueController.php';
require_once APP_ROOT . '/src/Admin/ContactMessageController.php';
require_once APP_ROOT . '/src/Admin/ReportController.php';
require_once APP_ROOT . '/src/Admin/InboxController.php';
require_once APP_ROOT . '/src/Admin/UpdateController.php';
require_once APP_ROOT . '/src/Admin/AdController.php';
require_once APP_ROOT . '/src/Admin/SupportController.php';
AdminController::routes();
AdminVideoController::routes();
AdminAlbumController::routes();
AdminAlbumCategoryController::routes();
AdminAlbumTagController::routes();
AdminAlbumPerformerController::routes();
AdminAlbumChannelController::routes();
AdminCategoryController::routes();
AdminTagController::routes();
AdminPerformerController::routes();
AdminUserController::routes();
AdminCommentController::routes();
AdminPageController::routes();
AdminSettingController::routes();
AdminPluginController::routes();
AdminThemeController::routes();
AdminChannelController::routes();
AdminLanguageController::routes();
AdminImportController::routes();
AdminFeedSourceController::routes();
AdminCatalogueController::routes();
AdminContactMessageController::routes();
AdminReportController::routes();
AdminInboxController::routes();
AdminUpdateController::routes();
AdminAdController::routes();
AdminSupportController::routes();
Ads::registerRoutes();
 
Router::get('/api/storage-monitor-download', function () {
    Auth::requireAdmin();
    $storageId = (int)($_GET['storage_id'] ?? 0);
    $script = StorageMonitorScript::generate();
    if ($storageId > 0) {
        $s = MediaStorage::get($storageId);
        if ($s) {
            $cfg = is_array($s['config']) ? $s['config'] : (json_decode($s['config'] ?: '{}', true) ?: []);
            $key = $cfg['monitor_key'] ?? '';
            if ($key !== '') $script = str_replace('%%SECRET%%', $key, $script);
        }
    }
    header('Content-Type: application/x-php');
    header('Content-Disposition: attachment; filename="tubepress-storage-monitor.php"');
    header('Content-Length: ' . strlen($script));
    echo $script;
    exit;
});

 
Router::get('/api/transcode-worker-download', function () {
    Auth::requireAdmin();
    $script = TranscodeWorkerScript::generate();
    header('Content-Type: application/x-php');
    header('Content-Disposition: attachment; filename="transcode-worker.php"');
    header('Content-Length: ' . strlen($script));
    echo $script;
    exit;
});

 
Router::post('/api/transcode-worker-link', function () {
    Auth::requireAdmin();
    if (!Router::verifyCsrf()) {
        http_response_code(403);
        echo json_encode(['error' => 'Invalid CSRF token']);
        exit;
    }
    header('Content-Type: application/json');
    $token = bin2hex(random_bytes(24));
    Database::transaction(function () use ($token) {
        Setting::set('worker_dl_token', $token);
        Setting::set('worker_dl_expires', (string)(time() + 180));
    });
    $url = rtrim(Setting::get('site_url', ''), '/') . '/api/transcode-worker-public?t=' . $token;
    echo json_encode(['url' => $url, 'expires_in' => 180]);
    exit;
});

 
Router::get('/api/transcode-worker-public', function () {
    $token = trim($_GET['t'] ?? '');
    $stored = Setting::get('worker_dl_token', '');
    $expires = (int)Setting::get('worker_dl_expires', '0');
    if ($token === '' || $stored === '' || !hash_equals($stored, $token) || time() > $expires) {
        http_response_code(403);
        echo "Link expired or invalid.\n";
        exit;
    }
    $script = TranscodeWorkerScript::generate();
    header('Content-Type: application/x-php');
    header('Content-Disposition: attachment; filename="transcode-worker.php"');
    header('Content-Length: ' . strlen($script));
    echo $script;
    exit;
});

 
Router::post('/api/transcode-callback', function () {
    header('Content-Type: application/json');
    $apiKey = $_SERVER['HTTP_X_API_KEY'] ?? '';
    if ($apiKey === '') { http_response_code(401); echo json_encode(['error' => 'Missing API key']); exit; }

    $input = json_decode(file_get_contents('php://input'), true);
    $result = TranscodeManager::handleCallback($input ?: [], $apiKey);
    http_response_code($result['code']);
    echo json_encode(array_diff_key($result, ['code' => 1]));
    exit;
});

 
Router::get('/api/transcode-job-check', function () {
    header('Content-Type: application/json');
    $apiKey = $_SERVER['HTTP_X_API_KEY'] ?? '';
    if ($apiKey === '') { http_response_code(401); echo json_encode(['error' => 'Missing API key']); exit; }
    $server = Database::fetchOne('SELECT id FROM transcode_servers WHERE api_key = ?', [$apiKey]);
    if (!$server) { http_response_code(401); echo json_encode(['error' => 'Invalid API key']); exit; }
    $jobId = (int)($_GET['job_id'] ?? 0);
    $job = Database::fetchOne("SELECT j.status, v.id as vid FROM transcode_jobs j LEFT JOIN videos v ON v.id = j.video_id WHERE j.id = ?", [$jobId]);
    if (!$job) { echo json_encode(['valid' => false, 'reason' => 'deleted']); exit; }
    if (!$job['vid']) { echo json_encode(['valid' => false, 'reason' => 'video_deleted']); exit; }
    if ($job['status'] === 'failed') { echo json_encode(['valid' => false, 'reason' => 'failed']); exit; }
    echo json_encode(['valid' => true]);
    exit;
});

 
Router::post('/api/transcode-progress', function () {
    header('Content-Type: application/json');
    $apiKey = $_SERVER['HTTP_X_API_KEY'] ?? '';
    if ($apiKey === '') { http_response_code(401); echo json_encode(['error' => 'Missing API key']); exit; }
    $server = Database::fetchOne('SELECT id FROM transcode_servers WHERE api_key = ?', [$apiKey]);
    if (!$server) { http_response_code(401); echo json_encode(['error' => 'Invalid API key']); exit; }
    $input = json_decode(file_get_contents('php://input'), true);
    $jobId = (int)($input['job_id'] ?? 0);
    $progress = max(0, min(99, (int)($input['progress'] ?? 0)));
    $stage = $input['stage'] ?? null;
    $validStages = ['downloading', 'transcoding', 'uploading'];
    if ($stage !== null && !in_array($stage, $validStages, true)) $stage = null;
    if ($jobId > 0) {
        $job = Database::fetchOne("SELECT status FROM transcode_jobs WHERE id = ?", [$jobId]);
        if (!$job || $job['status'] !== 'processing') {
            echo json_encode(['ok' => false, 'cancel' => true]);
            exit;
        }
        $update = ['progress' => $progress];
        if ($stage !== null) $update['stage'] = $stage;
        Database::update('transcode_jobs', $update, 'id = ? AND status = ?', [$jobId, 'processing']);
        TranscodeManager::heartbeat($jobId);
    }
    echo json_encode(['ok' => true]);
    exit;
});

 
Router::post('/api/transcode-upload', function () {
    set_time_limit(600);
    header('Content-Type: application/json');
    $apiKey = $_SERVER['HTTP_X_API_KEY'] ?? '';
    if ($apiKey === '') { http_response_code(401); echo json_encode(['error' => 'Missing API key']); exit; }

    $result = TranscodeManager::handleUpload($apiKey);
    http_response_code($result['code']);
    echo json_encode(array_diff_key($result, ['code' => 1]));
    exit;
});

 
Router::post('/api/transcode-upload-chunk', function () {
    set_time_limit(1800);
    header('Content-Type: application/json');
    $apiKey = $_SERVER['HTTP_X_API_KEY'] ?? '';
    if ($apiKey === '') { http_response_code(401); echo json_encode(['error' => 'Missing API key']); exit; }

    $result = TranscodeManager::handleUploadChunk($apiKey);
    http_response_code($result['code']);
    echo json_encode(array_diff_key($result, ['code' => 1]));
    exit;
});

 
Router::get('/api/plugin-status', function () {
    header('Content-Type: application/json');
    $slug = trim($_GET['slug'] ?? '');
    $token = trim($_GET['token'] ?? '');
    $expected = Setting::get('licence_verification_token', '');

    if ($expected === '' || !hash_equals($expected, $token)) {
        http_response_code(403);
        echo json_encode(['error' => 'invalid_token']);
        exit;
    }

    $active = PluginManager::isActive($slug) || (ThemeManager::active() === $slug);
    echo json_encode(['slug' => $slug, 'active' => $active]);
    exit;
});

 
SecureMedia::routes();

 
require_once APP_ROOT . '/src/Front/CronWorkerController.php';
CronWorkerController::routes();

 
require_once APP_ROOT . '/src/Front/HomeController.php';
require_once APP_ROOT . '/src/Front/VideoController.php';
require_once APP_ROOT . '/src/Front/CategoryController.php';
require_once APP_ROOT . '/src/Front/TagController.php';
require_once APP_ROOT . '/src/Front/PerformerController.php';
require_once APP_ROOT . '/src/Front/AlbumController.php';
require_once APP_ROOT . '/src/Front/AlbumTaxonomyController.php';
require_once APP_ROOT . '/src/Front/SearchController.php';
require_once APP_ROOT . '/src/Front/AuthController.php';
require_once APP_ROOT . '/src/Front/FavoriteController.php';
require_once APP_ROOT . '/src/Front/HistoryController.php';
require_once APP_ROOT . '/src/Front/PageController.php';
require_once APP_ROOT . '/src/Front/ChannelController.php';
require_once APP_ROOT . '/src/Front/VideoListController.php';
require_once APP_ROOT . '/src/Front/ContactController.php';
require_once APP_ROOT . '/src/Front/ReportController.php';
require_once APP_ROOT . '/src/Front/SitemapController.php';

FrontHomeController::routes();
FrontVideoController::routes();
FrontCategoryController::routes();
FrontTagController::routes();
FrontPerformerController::routes();
FrontAlbumController::routes();
FrontAlbumTaxonomyController::routes();
FrontSearchController::routes();
FrontAuthController::routes();
FrontFavoriteController::routes();
FrontHistoryController::routes();
FrontChannelController::routes();
FrontVideoListController::routes();

FrontContactController::routes();
FrontReportController::routes();
SitemapController::routes();

HookSystem::doAction('routes.registered');

 
FrontPageController::routes();

Router::dispatch();
