<?php

declare(strict_types=1);

class InstallController
{
    public static function routes(): void
    {
         
        if (App::isInstalled()) {
            return;
        }
        Router::get('/install', [self::class, 'welcome']);
        Router::get('/install/requirements', [self::class, 'requirements']);
        Router::get('/install/database', [self::class, 'database']);
        Router::post('/install/database', [self::class, 'databasePost']);
        Router::get('/install/admin', [self::class, 'admin']);
        Router::post('/install/admin', [self::class, 'adminPost']);
        Router::get('/install/settings', [self::class, 'settings']);
        Router::post('/install/settings', [self::class, 'settingsPost']);
        Router::get('/install/complete', [self::class, 'complete']);
    }

    public static function welcome(): void
    {
        Router::render('install/welcome', ['step' => 1]);
    }

    public static function requirements(): void
    {
        self::ensureWritableDirs();
        $phpVersion = PHP_VERSION;
         
         
         
        $minPhp = defined('TUBEPRESS_MIN_PHP') ? TUBEPRESS_MIN_PHP : '8.2.0';
        $minPhpLabel = implode('.', array_slice(explode('.', $minPhp), 0, 2));  

        $checks = [
            [
                'name' => 'PHP Version',
                'description' => 'PHP ' . $minPhpLabel . ' or higher is required to run TubePress.',
                'passed' => version_compare($phpVersion, $minPhp, '>='),
                'current' => 'PHP ' . $phpVersion,
                'fix' => 'Upgrade PHP to version ' . $minPhpLabel . ' or higher. Contact your hosting provider or run: <code>sudo apt install php' . $minPhpLabel . '</code>',
                'category' => 'php',
                'required' => true,
            ],
            [
                'name' => 'MySQL Support',
                'description' => 'Required to connect to your MySQL database.',
                'passed' => extension_loaded('pdo') && extension_loaded('pdo_mysql'),
                'current' => extension_loaded('pdo_mysql') ? 'Installed' : 'Not installed',
                'fix' => 'Install the MySQL PHP extension: <code>sudo apt install php-mysql</code> then restart your web server.',
                'category' => 'php',
                'required' => true,
            ],
            [
                'name' => 'String Functions (mbstring)',
                'description' => 'Required for proper handling of special characters, URLs and international text.',
                'passed' => extension_loaded('mbstring'),
                'current' => extension_loaded('mbstring') ? 'Installed' : 'Not installed',
                'fix' => 'Install the mbstring extension: <code>sudo apt install php-mbstring</code> then restart your web server.',
                'category' => 'php',
                'required' => true,
            ],
            [
                'name' => 'File Type Detection (fileinfo)',
                'description' => 'Required for detecting file types when uploading videos and images.',
                'passed' => extension_loaded('fileinfo'),
                'current' => extension_loaded('fileinfo') ? 'Installed' : 'Not installed',
                'fix' => 'Install the fileinfo extension: <code>sudo apt install php-fileinfo</code> then restart your web server.',
                'category' => 'php',
                'required' => true,
            ],
            [
                'name' => 'cURL',
                'description' => 'Recommended for catalogue downloads and marketplace features.',
                'passed' => extension_loaded('curl'),
                'current' => extension_loaded('curl') ? 'Installed' : 'Not installed',
                'fix' => 'Install the cURL extension: <code>sudo apt install php-curl</code> then restart your web server.',
                'category' => 'php',
                'required' => false,
            ],
            [
                'name' => 'ZIP Archives',
                'description' => 'Recommended for installing and updating plugins and themes from the admin panel.',
                'passed' => extension_loaded('zip'),
                'current' => extension_loaded('zip') ? 'Installed' : 'Not installed',
                'fix' => 'Install the ZIP extension: <code>sudo apt install php-zip</code> then restart your web server.',
                'category' => 'php',
                'required' => false,
            ],
            [
                'name' => 'Image Processing (GD)',
                'description' => 'Recommended for generating thumbnails and processing uploaded images.',
                'passed' => extension_loaded('gd') || extension_loaded('imagick'),
                'current' => extension_loaded('gd') ? 'GD installed' : (extension_loaded('imagick') ? 'Imagick installed' : 'Not installed'),
                'fix' => 'Install GD: <code>sudo apt install php-gd</code> or Imagick: <code>sudo apt install php-imagick</code> then restart your web server.',
                'category' => 'php',
                'required' => false,
            ],
            [
                'name' => 'URL Rewriting',
                'description' => 'Required for clean URLs (e.g., /video/my-video instead of ?id=123).',
                'passed' => self::checkRewrite(),
                'current' => self::checkRewrite() ? 'Available' : 'Unknown',
                'fix' => '<strong>Apache:</strong> Enable mod_rewrite: <code>sudo a2enmod rewrite</code> and set <code>AllowOverride All</code> in your VirtualHost.<br><strong>Nginx:</strong> Make sure your server block has <code>try_files $uri $uri/ /index.php?$query_string;</code>',
                'category' => 'server',
                'required' => true,
            ],
            [
                'name' => 'PHP Sessions',
                'description' => 'Required to keep the setup wizard secure and remember each step.',
                'passed' => self::checkSessions(),
                'current' => self::checkSessions() ? 'Working' : 'Not writable',
                'fix' => 'PHP cannot write session files. Set a writable <code>session.save_path</code> in your php.ini (a folder you own), then restart your web server &mdash; or ask your host to enable PHP sessions.',
                'category' => 'server',
                'required' => true,
            ],
            [
                'name' => 'Config Directory',
                'description' => 'TubePress needs to save your database settings to the <code>config/</code> folder.',
                'passed' => is_writable(APP_ROOT . '/config'),
                'current' => is_writable(APP_ROOT . '/config') ? 'Writable' : 'Not writable',
                'fix' => 'Set the correct permissions: <code>chmod 755 config/</code> and make sure your web server user owns it: <code>chown www-data:www-data config/</code>',
                'category' => 'permissions',
                'required' => true,
            ],
            [
                'name' => 'Storage Directory',
                'description' => 'Used for logs and temporary files.',
                'passed' => is_writable(APP_ROOT . '/storage'),
                'current' => is_writable(APP_ROOT . '/storage') ? 'Writable' : 'Not writable',
                'fix' => 'Set permissions: <code>chmod -R 755 storage/</code> and <code>chown -R www-data:www-data storage/</code>',
                'category' => 'permissions',
                'required' => true,
            ],
            [
                'name' => 'Uploads Directory',
                'description' => 'Where your videos, thumbnails and images will be stored.',
                'passed' => is_writable(APP_ROOT . '/public/uploads'),
                'current' => is_writable(APP_ROOT . '/public/uploads') ? 'Writable' : 'Not writable',
                'fix' => 'Set permissions: <code>chmod -R 755 public/uploads/</code> and <code>chown -R www-data:www-data public/uploads/</code>',
                'category' => 'permissions',
                'required' => true,
            ],
        ];

         
        $requiredChecks = array_filter($checks, fn($c) => $c['required']);
        $allPassed = !in_array(false, array_column($requiredChecks, 'passed'), true);
        $failedCount = count(array_filter($requiredChecks, fn($c) => !$c['passed']));

         
        $serverSoftware = $_SERVER['SERVER_SOFTWARE'] ?? '';
        if (stripos($serverSoftware, 'nginx') !== false) {
            $webServer = 'Nginx';
        } elseif (stripos($serverSoftware, 'apache') !== false) {
            $webServer = 'Apache';
        } else {
            $webServer = 'Unknown';
        }

         
         
         
        if ($allPassed && empty($_GET['show'])) {
            Router::redirect('/install/database');
            return;
        }

        Router::render('install/requirements', [
            'step' => 2,
            'checks' => $checks,
            'allPassed' => $allPassed,
            'failedCount' => $failedCount,
            'webServer' => $webServer,
            'phpVersion' => $phpVersion,
        ]);
    }

    public static function database(): void
    {
        Router::render('install/database', ['step' => 3, 'error' => null]);
    }

    public static function databasePost(): void
    {
        if (!Router::verifyCsrf()) {
            Router::render('install/database', ['step' => 3, 'error' => 'Your session has expired. Please refresh the page and try again.']);
            return;
        }

        self::ensureWritableDirs();

        $host = trim($_POST['db_host'] ?? '127.0.0.1');
        if ($host === '') { $host = '127.0.0.1'; }
        $name = trim($_POST['db_name'] ?? '');
        $user = trim($_POST['db_user'] ?? '');
        $pass = $_POST['db_password'] ?? '';

        if ($name === '' || $user === '') {
            Router::render('install/database', ['step' => 3, 'error' => 'Database name and username are required.']);
            return;
        }

         
         
        $safeName = preg_replace('/[^A-Za-z0-9_-]/', '', $name);
        if ($safeName === '') {
            Router::render('install/database', ['step' => 3, 'error' => 'Invalid database name. Use only letters, numbers, underscores and hyphens.']);
            return;
        }
        if ($safeName !== $name) {
            Router::render('install/database', ['step' => 3, 'error' => "Invalid characters in database name. Only letters, numbers, underscores and hyphens are allowed. Suggested name: {$safeName}"]);
            return;
        }

         
         
        [$dbHost, $dbPort, $dbSocket] = self::parseDbHost($host);
        $dsn = 'mysql:';
        if ($dbSocket !== null) {
            $dsn .= 'unix_socket=' . $dbSocket . ';';
        } else {
            $dsn .= 'host=' . $dbHost . ';';
            if ($dbPort !== null) { $dsn .= 'port=' . $dbPort . ';'; }
        }
        $dsn .= 'charset=utf8mb4';

        try {
            $pdo = new PDO(
                $dsn,
                $user,
                $pass,
                [
                    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                    PDO::ATTR_EMULATE_PREPARES   => false,
                ]
            );

             
             
             
            try {
                $pdo->exec("USE `{$safeName}`");
            } catch (PDOException $eUse) {
                try {
                    $pdo->exec("CREATE DATABASE IF NOT EXISTS `{$safeName}` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
                    $pdo->exec("USE `{$safeName}`");
                } catch (PDOException $eCreate) {
                    Router::render('install/database', ['step' => 3, 'error' => "The database \"{$safeName}\" does not exist and this database user is not allowed to create it. On shared hosting, create the database and grant your user access to it in your hosting control panel (cPanel/Plesk), then enter that exact name here."]);
                    return;
                }
            }

             
             
             
            try { $pdo->exec("ALTER DATABASE `{$safeName}` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); } catch (\Throwable $eAlter) {   }

             
            require_once APP_ROOT . '/src/Install/Migrator.php';
            Database::set($pdo);
            $results = Migrator::run($pdo);

             
            $errors = array_filter($results, fn($r) => $r['status'] === 'error');
            if (!empty($errors)) {
                Router::render('install/database', ['step' => 3, 'error' => 'The database tables could not be created. Make sure the database user has full privileges (CREATE, ALTER, INSERT, etc.) and try again.']);
                return;
            }

             
             
             
            if ($dbSocket !== null) {
                $runtimeDsn = 'mysql:unix_socket=' . $dbSocket . ';dbname=' . $safeName . ';charset=utf8mb4';
            } else {
                $runtimeDsn = 'mysql:host=' . $dbHost . ($dbPort !== null ? ';port=' . $dbPort : '') . ';dbname=' . $safeName . ';charset=utf8mb4';
            }
            $configContent = self::buildDatabaseConfig($user, $pass, $runtimeDsn);

            $written = file_put_contents(APP_ROOT . '/config/database.php', $configContent);
            if ($written === false) {
                Router::render('install/database', ['step' => 3, 'error' => 'Could not write the database configuration file. Please check that the config/ directory is writable by the web server.']);
                return;
            }

             
            $_SESSION['install_db'] = true;

            Router::redirect('/install/admin');
        } catch (PDOException $e) {
            $msg = 'Could not connect to the database. ';
            if (str_contains($e->getMessage(), 'Access denied')) {
                $msg .= 'The username or password is incorrect.';
            } elseif (str_contains($e->getMessage(), 'Connection refused') || str_contains($e->getMessage(), 'No such file')) {
                $msg .= 'The database server is not reachable. Check the host address and make sure MySQL is running.';
            } else {
                $msg .= 'Please verify your credentials and that the MySQL server is running.';
            }
            Router::render('install/database', ['step' => 3, 'error' => $msg]);
        }
    }

    public static function admin(): void
    {
        if (empty($_SESSION['install_db'])) {
            Router::redirect('/install/database');
            return;
        }
        Router::render('install/admin', ['step' => 4, 'error' => null]);
    }

    public static function adminPost(): void
    {
        if (!Router::verifyCsrf()) {
            Router::render('install/admin', ['step' => 4, 'error' => 'Your session has expired. Please refresh the page and try again.']);
            return;
        }

        $username = trim($_POST['username'] ?? '');
        $email = trim($_POST['email'] ?? '');
        $password = $_POST['password'] ?? '';
        $passwordConfirm = $_POST['password_confirm'] ?? '';

        if ($username === '' || $email === '' || $password === '') {
            Router::render('install/admin', ['step' => 4, 'error' => 'All fields are required.']);
            return;
        }

        if (strlen($username) < 3 || strlen($username) > 50) {
            Router::render('install/admin', ['step' => 4, 'error' => 'Username must be between 3 and 50 characters.']);
            return;
        }

        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            Router::render('install/admin', ['step' => 4, 'error' => 'Invalid email address.']);
            return;
        }

        if (strlen($password) < 8) {
            Router::render('install/admin', ['step' => 4, 'error' => 'Password must be at least 8 characters.']);
            return;
        }

        if ($password !== $passwordConfirm) {
            Router::render('install/admin', ['step' => 4, 'error' => 'Passwords do not match.']);
            return;
        }

        try {
            require_once APP_ROOT . '/config/database.php';
            $pdo = getDbConnection();
            $hash = Auth::hashPassword($password);

            $stmt = $pdo->prepare('INSERT INTO users (username, email, password_hash, role, is_active) VALUES (?, ?, ?, ?, 1)');
            $stmt->execute([$username, $email, $hash, 'admin']);

            $_SESSION['install_admin'] = true;
            Router::redirect('/install/settings');
        } catch (PDOException $e) {
            $msg = 'Could not create the admin account. ';
            if (str_contains($e->getMessage(), 'Duplicate entry')) {
                $msg .= 'This username or email already exists.';
            } else {
                $msg .= 'Please check your database connection and try again.';
            }
            Router::render('install/admin', ['step' => 4, 'error' => $msg]);
        }
    }

    public static function settings(): void
    {
        if (empty($_SESSION['install_admin'])) {
            Router::redirect('/install/admin');
            return;
        }

        Router::render('install/settings', ['step' => 5, 'error' => null, 'defaultUrl' => self::detectBaseUrl()]);
    }

    public static function settingsPost(): void
    {
        if (!Router::verifyCsrf()) {
            Router::render('install/settings', ['step' => 5, 'error' => 'Your session has expired. Please refresh the page and try again.', 'defaultUrl' => self::detectBaseUrl()]);
            return;
        }

        try {
            require_once APP_ROOT . '/config/database.php';
            $pdo = getDbConnection();
            Database::set($pdo);

             
             
             
            $detectedUrl = self::detectBaseUrl();
            $siteName = trim($_POST['site_name'] ?? '');
            $settings = [
                'site_name'        => $siteName !== '' ? $siteName : 'My Video Site',
                'site_description' => trim($_POST['site_description'] ?? ''),
                'site_url'         => rtrim((trim($_POST['site_url'] ?? '') ?: $detectedUrl), '/'),
                'videos_per_page'  => '24',
            ];

            foreach ($settings as $key => $value) {
                Setting::set($key, $value);
            }

            $_SESSION['install_settings'] = true;
            Router::redirect('/install/complete');
        } catch (PDOException $e) {
            Router::render('install/settings', ['step' => 5, 'error' => 'Could not save settings. Please check your database connection and try again.', 'defaultUrl' => self::detectBaseUrl()]);
        }
    }

    public static function complete(): void
    {
        if (empty($_SESSION['install_settings'])) {
            Router::redirect('/install');
            return;
        }

         
         
         
        try {
            require_once APP_ROOT . '/config/database.php';
            $pdo = getDbConnection();
            Database::set($pdo);
            require_once APP_ROOT . '/src/Install/DefaultPages.php';
            DefaultPages::seed();
            self::seedDefaultSettings();

             
            SeoManager::boot();
        } catch (\Throwable $e) {
             
             
            error_log('TubePress install: default seeding failed — ' . $e->getMessage());
        }

         
         
         
         
         
        foreach (['themes' => '../themes', 'templates' => '../templates'] as $link => $target) {
            $linkPath = APP_ROOT . '/public/' . $link;
            if (!file_exists($linkPath) && function_exists('symlink')) {
                @symlink($target, $linkPath);
            }
        }

        $written = file_put_contents(APP_ROOT . '/config/installed.php', "<?php return true;\n");
        if ($written === false) {
            Router::render('install/complete', ['step' => 6, 'error' => 'Could not create the installation marker file. Please check that the config/ directory is writable.']);
            return;
        }

         
        unset($_SESSION['install_db'], $_SESSION['install_admin'], $_SESSION['install_settings']);

        Router::render('install/complete', ['step' => 6]);
    }

    public static function seedDefaultSettings(): void
    {
        $defaults = [
             
            'active_theme'       => 'simply',

             
            'videos_per_page'    => '24',
            'videos_per_row'     => '5',
            'site_max_width'     => '1600',
            'site_padding_desktop' => '20',
            'site_padding_mobile'  => '10',
            'site_background_mode' => 'cover',

             
            'color_primary'         => '#3b82f6',
            'color_primary_opacity' => '100',

             
            'color_bg'              => '',
            'color_bg_opacity'      => '100',
            'color_bg_surface'      => '',
            'color_bg_surface_opacity' => '100',
            'color_bg_card'         => '',
            'color_bg_card_opacity' => '100',
            'color_bg_dark'         => '',
            'color_bg_dark_opacity' => '100',
            'color_text'            => '',
            'color_text_opacity'    => '100',
            'color_text_muted'      => '',
            'color_text_muted_opacity' => '100',
            'color_border'          => '',
            'color_border_opacity'  => '100',

             
            'dk_color_bg'              => '',
            'dk_color_bg_opacity'      => '100',
            'dk_color_bg_surface'      => '',
            'dk_color_bg_surface_opacity' => '100',
            'dk_color_bg_card'         => '',
            'dk_color_bg_card_opacity' => '100',
            'dk_color_bg_dark'         => '',
            'dk_color_bg_dark_opacity' => '100',
            'dk_color_text'            => '',
            'dk_color_text_opacity'    => '100',
            'dk_color_text_muted'      => '#f3f3f3',
            'dk_color_text_muted_opacity' => '100',
            'dk_color_border'          => '',
            'dk_color_border_opacity'  => '100',

             
            'menu_categories' => '1',
            'menu_tags'       => '0',
            'menu_pornstars'  => '0',
            'menu_channels'    => '0',
            'menu_search'     => '1',

             
            'menu_config' => json_encode([
                'items' => [
                    ['id' => 'home',           'type' => 'internal', 'label' => 'Home',         'icon' => 'house',        'children' => [], 'url' => '/'],
                    ['id' => 'new_videos',     'type' => 'internal', 'label' => 'New Videos',   'icon' => 'sparkles',     'children' => [], 'url' => '/videos/new'],
                    ['id' => 'top_rated',      'type' => 'internal', 'label' => 'Top Rated',    'icon' => 'star',         'children' => [], 'url' => '/videos/top-rated'],
                    ['id' => 'most_viewed',    'type' => 'internal', 'label' => 'Most Viewed',  'icon' => 'eye',          'children' => [], 'url' => '/videos/most-viewed'],
                    ['id' => 'most_favorited', 'type' => 'internal', 'label' => 'Most Favorited','icon' => 'heart',       'children' => [], 'url' => '/videos/most-favorited'],
                    ['id' => 'categories',     'type' => 'internal', 'label' => 'Categories',   'icon' => 'grid-2',       'children' => [], 'url' => '/categories'],
                    ['id' => 'tags',           'type' => 'internal', 'label' => 'Tags',         'icon' => 'tags',         'children' => [], 'url' => '/tags'],
                    ['id' => 'pornstars',      'type' => 'internal', 'label' => 'Pornstars',    'icon' => 'users',        'children' => [], 'url' => '/pornstars'],
                    ['id' => 'channels',        'type' => 'internal', 'label' => 'Channels',      'icon' => 'clapperboard', 'children' => [], 'url' => '/channels'],
                    ['id' => 'albums',          'type' => 'internal', 'label' => 'Albums',        'icon' => 'images',       'children' => [], 'url' => '/albums'],
                    ['id' => 'vtype_switcher', 'type' => 'internal', 'label' => 'Video Type Switcher', 'icon' => 'shuffle', 'children' => [], 'url' => '#'],
                ],
            ]),

             
            'footer_config' => json_encode([
                'columns' => [
                    ['type' => 'logo',       'title' => 'Column 1'],
                    ['type' => 'navigation', 'title' => 'Column 2'],
                    ['type' => 'pages',      'title' => 'Column 3', 'page_ids' => []],
                    ['type' => 'badges',     'title' => 'Column 4', 'badges' => [
                        ['icon' => 'shield', 'label' => '18+ Only'],
                        ['icon' => 'upload', 'label' => 'Free Content'],
                        ['icon' => 'video',  'label' => 'HD Videos'],
                    ]],
                ],
                'bottom' => [
                    'show_copyright'  => true,
                    'copyright_text'  => '',
                    'show_disclaimer' => true,
                    'disclaimer_text' => '',
                    'show_social'     => true,
                ],
                'social' => [
                    'twitter' => '', 'instagram' => '', 'reddit' => '',
                    'telegram' => '', 'discord' => '',
                ],
            ]),

             
            'card_border_radius'       => '5',
            'card_grid_gap'            => '4',
            'card_meta_left'           => 'views',
            'card_meta_right'          => 'time',
            'card_show_duration'       => '1',
            'card_show_thumbnail_hover' => '1',
            'card_show_title'          => '1',
            'card_title_lines'         => '1',

             
            'watch_show_views'      => '1',
            'watch_show_duration'   => '1',
            'watch_show_date'       => '1',
            'watch_show_likes'      => '1',
            'watch_show_favorites'  => '1',
            'watch_show_pornstars'  => '1',
            'watch_show_channels'    => '1',
            'watch_show_categories' => '1',
            'watch_show_tags'       => '1',
            'related_videos_count'  => '8',

             
            'player_playback_rate'        => '1',
            'player_allow_download'       => '0',
            'player_loop'                 => '0',
            'player_doubleclick_fullscreen' => '1',

             
            'default_sort'            => 'newest',
            'categories_default_sort' => 'trending',
            'performers_default_sort' => 'alphabetical',
            'channels_default_sort'    => 'alphabetical',

             
            'categories_per_page' => '30',
            'categories_per_row'  => '5',
            'performers_per_page' => '30',
            'performers_per_row'  => '6',
            'channels_per_page'    => '30',
            'channels_per_row'     => '6',

             
            'comments_enabled'    => '1',
            'comments_moderation' => '1',
            'spam_honeypot'       => '1',
            'spam_timegate'       => '1',
            'spam_timegate_seconds' => '3',
            'spam_ratelimit'      => '1',
            'spam_ratelimit_hour' => '5',
            'spam_ratelimit_day'  => '30',
            'spam_duplicate'      => '1',
            'spam_duplicate_window' => '60',
            'spam_links'          => '1',
            'spam_max_links'      => '0',
            'spam_length'         => '1',
            'spam_min_length'     => '2',
            'spam_max_length'     => '5000',

             
            'registration_enabled' => '0',
            'channels_as_users'    => '1',
            'timezone'             => 'UTC',
            'mail_method'          => 'php',
            'smtp_encryption'      => 'tls',
            'smtp_port'            => '587',

             
            'allowed_image_types' => 'jpg,jpeg,png,gif,webp',
            'allowed_video_types' => 'mp4,webm,ogg',
            'upload_max_size'     => '524288000',

             
            'simply_dark_mode_default'  => 'light',
            'simply_dark_mode_enabled'  => '1',
            'simply_nav_style'          => 'full',
            'simply_hp_default_sort'    => 'newest',
            'simply_hp_sort_title_newest'    => 'LATEST VIDEOS',
            'simply_hp_sort_title_popular'   => 'MOST VIEWED',
            'simply_hp_sort_title_top_rated' => 'TOP RATED',
            'simply_hp_sort_title_trending'  => 'TRENDING',
            'simply_hp_watched_enabled' => '1',
            'simply_performers_per_row' => '6',
            'simply_channels_per_row'    => '6',
            'simply_topbar_enabled'     => '0',

             
            'import_ai_desc_prompt'      => 'Rewrite this video description to be unique and SEO-friendly. Keep it concise (2-3 sentences max). Do NOT use markdown or HTML.',
            'import_ai_title_prompt'     => 'Rewrite this video title to be unique and SEO-friendly while keeping the same meaning. Keep it natural and under 80 characters. Do NOT add quotes around the title.',
            'import_ai_translate_prompt' => "Translate this English video title (max 60 chars each).\n\nRULES:\n1. Translate ALL words to target language (NO mixing languages)\n2. Keep same meaning (do not add or remove words)\n3. Natural phrasing (native speaker quality)",
        ];

        foreach ($defaults as $key => $value) {
             
            $existing = Setting::get($key, "\0");
            if ($existing === "\0") {
                Setting::set($key, $value);
            }
        }
    }

    

    public static function ensureWritableDirs(): void
    {
        foreach ([
            APP_ROOT . '/config',
            APP_ROOT . '/storage',
            APP_ROOT . '/storage/logs',
            APP_ROOT . '/storage/tmp',
            APP_ROOT . '/public/uploads',
        ] as $dir) {
            if (!is_dir($dir)) {
                @mkdir($dir, 0775, true);
            }
        }
    }

    

    public static function parseDbHost(string $input): array
    {
        $input = trim($input);
        if ($input === '') {
            return ['127.0.0.1', null, null];
        }
        if ($input[0] === '/') {
            return [null, null, $input];  
        }
        if (preg_match('/^\[([^\]]+)\](?::(\d+))?$/', $input, $m)) {
            return [$m[1], (isset($m[2]) && $m[2] !== '') ? (int) $m[2] : null, null];  
        }
        if (substr_count($input, ':') === 1) {
            [$h, $p] = explode(':', $input, 2);
            $h = trim($h);
            if ($p !== '' && ctype_digit($p)) {
                return [$h !== '' ? $h : '127.0.0.1', (int) $p, null];
            }
        }
        return [$input, null, null];
    }

    

    public static function buildDatabaseConfig(string $user, string $pass, string $dsn): string
    {
        $eUser = var_export($user, true);
        $ePass = var_export($pass, true);
        $eDsn = var_export($dsn, true);

        return <<<PHP
<?php

declare(strict_types=1);

// Guarded so a double include (e.g. a worker bootstrap loading app.php + database.php)
// never fatals with "Cannot redeclare getDbConnection()".
if (!function_exists('getDbConnection')) {
function getDbConnection(bool \$forceNew = false): PDO
{
    static \$pdo = null;

    if (\$forceNew) {
        \$pdo = null;
    }

    if (\$pdo === null) {
        \$pdo = new PDO(
            {$eDsn},
            {$eUser},
            {$ePass},
            [
                PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                PDO::ATTR_EMULATE_PREPARES   => false,
            ]
        );
    }

    return \$pdo;
}
}
PHP;
    }

    

    public static function detectBaseUrl(): string
    {
        $https = (!empty($_SERVER['HTTPS']) && strtolower((string) $_SERVER['HTTPS']) !== 'off')
            || (int) ($_SERVER['SERVER_PORT'] ?? 0) === 443
            || strtolower((string) ($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '')) === 'https'
            || strtolower((string) ($_SERVER['HTTP_X_FORWARDED_SSL'] ?? '')) === 'on';
        $host = $_SERVER['HTTP_X_FORWARDED_HOST'] ?? $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'localhost';
        if (str_contains($host, ',')) {
            $host = trim(explode(',', $host)[0]);
        }
        return ($https ? 'https' : 'http') . '://' . $host;
    }

    

    private static function checkSessions(): bool
    {
        if (strtolower((string) ini_get('session.save_handler')) !== 'files') {
            return true;
        }
        $path = (string) session_save_path();
        if ($path === '') {
            $path = sys_get_temp_dir();
        }
        if (str_contains($path, ';')) {
            $parts = explode(';', $path);
            $path = (string) end($parts);
        }
        return $path !== '' && is_writable($path);
    }

    private static function checkRewrite(): bool
    {
        $server = $_SERVER['SERVER_SOFTWARE'] ?? '';

         
        if (stripos($server, 'nginx') !== false) {
            return true;
        }

         
        if (function_exists('apache_get_modules')) {
            return in_array('mod_rewrite', apache_get_modules(), true);
        }

         
        return true;
    }
}
