<?php

declare(strict_types=1);

HookSystem::addAction('routes.registered', function (): void {
    Router::get('/admin/appearance', ['SimplyAppearance', 'render']);
    Router::post('/admin/appearance', ['SimplyAppearance', 'save']);
});

HookSystem::addAction('admin.sidebar_menu', function (string $activeMenu): void {
    ?>
    <a href="/admin/appearance" class="flex items-center gap-2.5 px-5 py-2.5 text-sm no-underline transition-all duration-150 <?= $activeMenu === 'appearance' ? 'text-white bg-primary-600' : 'text-gray-400 hover:text-white hover:bg-gray-800' ?>">
        <svg viewBox="0 0 24 24" class="w-[18px] h-[18px] shrink-0" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
        Appearance
    </a>
    <?php
});

HookSystem::addFilter('admin.subtabs.appearance', function (array $subs): array {
    $coreSubs = [
        'colors' => 'Colors',
        'menu'   => 'Menu',
        'layout' => 'Layout',
        'watch'  => 'Watch',
    ];

    if (count(Video::availableTypes()) >= 2) {
        $coreSubs['videotypes'] = 'Video Types';
    }

    return array_merge($coreSubs, $subs);
});

HookSystem::addAction('admin.appearance_render.colors', function (array $vars): void {
    extract($vars, EXTR_SKIP);
    require __DIR__ . '/colors.php';
});

HookSystem::addAction('admin.appearance_render.menu', function (array $vars): void {
    extract($vars, EXTR_SKIP);
    require __DIR__ . '/menu.php';
});

HookSystem::addAction('admin.appearance_render.layout', function (array $vars): void {
    extract($vars, EXTR_SKIP);
    require __DIR__ . '/layout.php';
});

HookSystem::addAction('admin.appearance_render.watch', function (array $vars): void {
    extract($vars, EXTR_SKIP);
    require __DIR__ . '/watch.php';
});

HookSystem::addAction('admin.appearance_render.videotypes', function (array $vars): void {
    extract($vars, EXTR_SKIP);
    require __DIR__ . '/videotypes.php';
});

HookSystem::addAction('admin.appearance_save.colors', function (): void {
    $colorKeys = ['color_primary',
                  'color_bg','color_bg_surface','color_bg_card','color_bg_dark',
                  'color_text','color_text_muted','color_border',
                  'dk_color_primary',
                  'dk_color_bg','dk_color_bg_surface','dk_color_bg_card','dk_color_bg_dark',
                  'dk_color_text','dk_color_text_muted','dk_color_border'];
    foreach ($colorKeys as $ck) {
        $val = trim($_POST[$ck] ?? '');
        if ($val !== '' && !preg_match('/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/', $val)) {
            $val = '';
        }
        Setting::set($ck, $val);
        $opVal = (int) ($_POST[$ck . '_opacity'] ?? 100);
        Setting::set($ck . '_opacity', (string) max(0, min(100, $opVal)));
    }

     
    Setting::set('simply_dark_mode_enabled', isset($_POST['simply_dark_mode_enabled']) ? '1' : '0');
    $dmDefault = ($_POST['simply_dark_mode_default'] ?? 'light');
    Setting::set('simply_dark_mode_default', in_array($dmDefault, ['light', 'dark'], true) ? $dmDefault : 'light');
});

HookSystem::addAction('admin.appearance_save.menu', function (): void {
    $menuConfig = MenuConfig::fromPost($_POST['menu_json'] ?? '');
    AdminSettingController::syncInternalMenuLabels($menuConfig);
    MenuConfig::save($menuConfig);
    Setting::set('menu_search', isset($_POST['menu_search']) ? '1' : '0');
    HookSystem::doAction('admin.appearance_save.menu.after');
});

HookSystem::addAction('admin.appearance_save.layout', function (): void {
    $maxW = (int) ($_POST['site_max_width'] ?? 1800);
    Setting::set('site_max_width', (string) max(1000, min(2400, $maxW)));
    $padDesktop = (int) ($_POST['site_padding_desktop'] ?? 24);
    Setting::set('site_padding_desktop', (string) max(0, min(80, $padDesktop)));
    $padMobile = (int) ($_POST['site_padding_mobile'] ?? 10);
    Setting::set('site_padding_mobile', (string) max(0, min(40, $padMobile)));
    Setting::set('videos_per_page', (string) max(4, min(120, (int) ($_POST['videos_per_page'] ?? 20))));
    $row = (int) ($_POST['videos_per_row'] ?? 5);
    Setting::set('videos_per_row', (string) max(4, min(6, $row)));
    $defaultSort = $_POST['default_sort'] ?? 'newest';
    $validSorts = array_keys(HookSystem::applyFilter('front.sort_tabs', [
        'newest' => 'Newest', 'popular' => 'Most Viewed', 'top_rated' => 'Top Rated',
    ]));
    if (!in_array($defaultSort, $validSorts, true)) {
        $defaultSort = 'newest';
    }
    Setting::set('default_sort', $defaultSort);
    $catRow = (int) ($_POST['categories_per_row'] ?? 5);
    Setting::set('categories_per_row', (string) max(3, min(6, $catRow)));
    $catPP = (int) ($_POST['categories_per_page'] ?? 30);
    Setting::set('categories_per_page', (string) max(6, min(120, $catPP)));
    $catDefaultSort = $_POST['categories_default_sort'] ?? 'alphabetical';
    $validCatSorts = array_keys(HookSystem::applyFilter('front.category_sort_tabs', [
        'alphabetical' => 'Alphabetical', 'popularity' => 'Popularity',
    ]));
    if (!in_array($catDefaultSort, $validCatSorts, true)) {
        $catDefaultSort = 'alphabetical';
    }
    Setting::set('categories_default_sort', $catDefaultSort);
    $perfPP = (int) ($_POST['performers_per_page'] ?? 30);
    Setting::set('performers_per_page', (string) max(6, min(120, $perfPP)));
    $perfDefaultSort = $_POST['performers_default_sort'] ?? 'alphabetical';
    $validPerfSorts = array_keys(HookSystem::applyFilter('front.performer_sort_tabs', [
        'alphabetical' => 'Alphabetical', 'popularity' => 'Popularity',
    ]));
    if (!in_array($perfDefaultSort, $validPerfSorts, true)) {
        $perfDefaultSort = 'alphabetical';
    }
    Setting::set('performers_default_sort', $perfDefaultSort);
    $channelPP = (int) ($_POST['channels_per_page'] ?? 30);
    Setting::set('channels_per_page', (string) max(6, min(120, $channelPP)));
    $channelDefaultSort = $_POST['channels_default_sort'] ?? 'alphabetical';
    $validChannelSorts = array_keys(HookSystem::applyFilter('front.channel_sort_tabs', [
        'alphabetical' => 'Alphabetical', 'popularity' => 'Popularity',
    ]));
    if (!in_array($channelDefaultSort, $validChannelSorts, true)) {
        $channelDefaultSort = 'alphabetical';
    }
    Setting::set('channels_default_sort', $channelDefaultSort);

     
    Setting::set('albums_per_page', (string) max(4, min(120, (int) ($_POST['albums_per_page'] ?? 24))));
    Setting::set('albums_per_row', (string) max(4, min(6, (int) ($_POST['albums_per_row'] ?? 5))));
    $albDefaultSort = $_POST['albums_default_sort'] ?? 'newest';
    $validAlbSorts = array_keys(HookSystem::applyFilter('front.album_sort_tabs', [
        'newest' => 'Newest', 'popular' => 'Most Viewed', 'top_rated' => 'Top Rated', 'most_images' => 'Most Images', 'trending' => 'Trending',
    ]));
    if (!in_array($albDefaultSort, $validAlbSorts, true)) {
        $albDefaultSort = 'newest';
    }
    Setting::set('albums_default_sort', $albDefaultSort);

     
    $albDisplay = $_POST['albums_display_mode'] ?? 'grid';
    Setting::set('albums_display_mode', in_array($albDisplay, ['grid', 'masonry'], true) ? $albDisplay : 'grid');
    $albNav = $_POST['albums_nav_mode'] ?? 'pages';
    Setting::set('albums_nav_mode', in_array($albNav, ['pages', 'infinite'], true) ? $albNav : 'pages');

     
    foreach (['categories', 'channels', 'performers', 'tags'] as $albSk) {
        Setting::set('albums_sidebar_' . $albSk, isset($_POST['albums_sidebar_' . $albSk]) ? '1' : '0');
    }
});

HookSystem::addAction('admin.appearance_save.watch', function (): void {
     
    if (($_POST['_seg'] ?? 'videos') === 'albums') {
        foreach (['album_show_views','album_show_date','album_show_likes','album_show_favorites',
                  'album_show_pornstars','album_show_channels','album_show_categories','album_show_tags',
                  'album_allow_download'] as $cb) {
            Setting::set($cb, isset($_POST[$cb]) ? '1' : '0');
        }
        Setting::set('related_albums_count', (string) max(0, min(24, (int) ($_POST['related_albums_count'] ?? 12))));
        return;
    }
    foreach (['watch_show_views','watch_show_duration','watch_show_date',
              'watch_show_likes','watch_show_favorites',
              'watch_show_pornstars','watch_show_channels',
              'watch_show_categories','watch_show_tags',
              'player_playback_rate','player_allow_download','player_loop','player_doubleclick_fullscreen'] as $cb) {
        Setting::set($cb, isset($_POST[$cb]) ? '1' : '0');
    }
    $relCount = max(2, min(20, (int) ($_POST['related_videos_count'] ?? 8)));
    Setting::set('related_videos_count', (string) $relCount);
    $dq = $_POST['player_default_quality'] ?? 'auto';
    Setting::set('player_default_quality', in_array($dq, ['auto','1080','720','480','360'], true) ? $dq : 'auto');
});

HookSystem::addAction('admin.appearance_save.videotypes', function (): void {
    $newDefault = $_POST['default_video_type'] ?? '';
    if (in_array($newDefault, Video::VALID_TYPES, true)) {
        Setting::set('default_video_type', $newDefault);
    }

    $labels = $_POST['type_label'] ?? [];
    foreach (Video::VALID_TYPES as $code) {
        $label = trim($labels[$code] ?? '');
        if ($label !== '') {
            Setting::set('seo_type_label_' . $code, $label);
        }
    }

    $slugs = $_POST['type_slug'] ?? [];
    $reserved = ['admin','install','sitemap','search','video','category','tag','performer','channel','page','login','register','api','embed'];
    $oldSlugsJson = Setting::get('video_type_old_slugs', '');
    $oldSlugs = ($oldSlugsJson !== '') ? (json_decode($oldSlugsJson, true) ?: []) : [];
    $newSlugs = [];
    foreach (Video::VALID_TYPES as $code) {
        $slug = trim($slugs[$code] ?? '');
        $slug = preg_replace('/[^a-z0-9-]/', '', strtolower($slug));
        if ($slug === '' || strlen($slug) < 2 || strlen($slug) > 30
            || !preg_match('/^[a-z0-9][a-z0-9-]*$/', $slug)
            || in_array($slug, $reserved, true)
            || (strlen($slug) === 2 && preg_match('/^[a-z]{2}$/', $slug))
        ) {
            $slug = $code;
        }
        $newSlugs[$code] = $slug;
    }

    if (count(array_unique($newSlugs)) < count($newSlugs)) {
        foreach ($newSlugs as $code => &$s) {
            $s = $code;
        }
        unset($s);
    }

    foreach (Video::VALID_TYPES as $code) {
        $currentSlug = Video::typeSlug($code);
        $newSlug = $newSlugs[$code];
        if ($currentSlug !== $newSlug) {
            $oldSlugs[$currentSlug] = $code;
            if (isset($oldSlugs[$newSlug])) {
                unset($oldSlugs[$newSlug]);
            }
        }
        Setting::set('video_type_slug_' . $code, $newSlug === $code ? '' : $newSlug);
    }
    Setting::set('video_type_old_slugs', json_encode($oldSlugs));

    Video::resetAvailableTypesCache();
    Setting::set('sitemap_dirty', '1');
});

class SimplyAppearance
{
    public static function render(): void
    {
        Auth::requireAdmin();

        $colorKeys = ['color_primary',
                      'color_bg','color_bg_surface','color_bg_card','color_bg_dark',
                      'color_text','color_text_muted','color_border',
                      'dk_color_primary',
                      'dk_color_bg','dk_color_bg_surface','dk_color_bg_card','dk_color_bg_dark',
                      'dk_color_text','dk_color_text_muted','dk_color_border'];
        $colorKeysWithOpacity = [];
        foreach ($colorKeys as $ck) {
            $colorKeysWithOpacity[] = $ck;
            $colorKeysWithOpacity[] = $ck . '_opacity';
        }
        $keys = array_merge($colorKeysWithOpacity, [
                 'menu_categories','menu_tags','menu_pornstars','menu_channels','menu_search',
                 'related_videos_count',
                 'watch_show_views','watch_show_duration','watch_show_date',
                 'watch_show_likes','watch_show_favorites',
                 'watch_show_pornstars','watch_show_channels',
                 'watch_show_categories','watch_show_tags',
                 'player_playback_rate','player_allow_download','player_loop','player_doubleclick_fullscreen','player_default_quality',
                 'videos_per_page','videos_per_row','default_sort',
                 'categories_per_row','categories_per_page','categories_default_sort',
                 'performers_per_page','performers_default_sort',
                 'channels_per_page','channels_default_sort',
                 'albums_per_page','albums_per_row','albums_default_sort',
                 'albums_display_mode','albums_nav_mode',
                 'albums_sidebar_categories','albums_sidebar_channels','albums_sidebar_performers','albums_sidebar_tags',
                 'site_logo','site_logo_dark','site_favicon',
                 'site_logo_height_desktop','site_logo_height_mobile',
                 'card_show_duration','card_show_title','card_meta_left','card_meta_right',
                 'card_grid_gap','card_border_radius','card_show_thumbnail_hover','card_title_lines',
                 'site_max_width','site_padding_desktop','site_padding_mobile',
                 'simply_dark_mode_enabled','simply_dark_mode_default',
                 'simply_topbar_enabled','simply_topbar_text','simply_topbar_link',
                 'simply_topbar_bg','simply_topbar_text_color',
]);

        $keys = HookSystem::applyFilter('admin.appearance_settings_keys', $keys);

        $subs = HookSystem::applyFilter('admin.subtabs.appearance', []);

        $activeSub = $_GET['sub'] ?? array_key_first($subs);
        if (!isset($subs[$activeSub])) {
            $activeSub = array_key_first($subs);
        }

        $data = [
            'pageTitle' => 'Appearance',
            'activeMenu' => 'appearance',
            'contentTemplate' => '_appearance',
            'settings' => Setting::getMany($keys),
            'subTabs' => $subs,
            'activeSub' => $activeSub,
        ];

        if ($activeSub === 'videotypes') {
            $defaultType = Video::defaultType();
            $vtConfig = [];
            foreach (Video::VALID_TYPES as $code) {
                $vtConfig[$code] = [
                    'label' => Video::typeLabel($code),
                    'slug' => Video::typeSlug($code),
                    'is_default' => ($code === $defaultType),
                ];
            }
            $data['videoTypeConfig'] = $vtConfig;
        }

        if ($activeSub === 'menu') {
            $data['menuConfig'] = MenuConfig::get();
            $data['hasMultipleVideoTypes'] = count(Video::availableTypes()) >= 2;
            $internalLabelKeys = ['home', 'categories', 'tags', 'pornstars', 'channels', 'albums', 'vtype_switcher'];
            foreach ($data['menuConfig']['items'] as &$_mi) {
                if (($_mi['type'] ?? '') === 'internal' && in_array($_mi['id'] ?? '', $internalLabelKeys, true)) {
                    $_mi['label'] = __($_mi['id']);
                }
                foreach ($_mi['children'] ?? [] as &$_ch) {
                    if (($_ch['type'] ?? '') === 'internal' && in_array($_ch['id'] ?? '', $internalLabelKeys, true)) {
                        $_ch['label'] = __($_ch['id']);
                    }
                }
                unset($_ch);
            }
            unset($_mi);
            $data['allPages'] = Page::allPublished();
            $data['menuLanguages'] = Translator::available();
            $data['menuDefaultLang'] = Translator::getDefaultCode();
            $data['menuInternalTranslations'] = AdminSettingController::loadInternalMenuTranslations();
        }

        Router::render('admin/appearance', $data);
    }

    public static function save(): void
    {
        Auth::requireAdmin();
        if (!Router::verifyCsrf()) {
            Router::redirect('/admin/appearance');
            return;
        }

        $sub = $_POST['_sub'] ?? 'colors';
        HookSystem::doAction('admin.appearance_save.' . $sub);

        $_SESSION['flash'] = ['type' => 'success', 'message' => 'Settings updated successfully.'];
        $redirect = '/admin/appearance';
        if ($sub !== '') {
            $redirect .= '?sub=' . $sub;
            $seg = $_POST['_seg'] ?? '';
            if ($seg !== '') {
                $redirect .= '&seg=' . urlencode($seg);
            }
        }
        Router::redirect($redirect);
    }
}
