<?php

namespace App\Http\Controllers\Admin;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\Translator;
use App\Models\Setting;
use App\Services\ActivityLogger;
use App\Services\PageCache;
use App\Services\UploadService;

class SettingsController extends Controller
{
    public function index(Request $request, array $params = []): void
    {
        $settings = Setting::getAllAsMap();
        $view = $this->app->service('view');
        $html = $view->renderAdmin('settings/index', [
            'pageTitle' => __('admin.settings.title'),
            'settings'  => $settings,
            'auth'      => $this->auth(),
            'csrf'      => $this->csrf(),
        ]);
        Response::html($html);
    }

    public function save(Request $request, array $params = []): void
    {
        $this->validateCsrf();

        // ── Handle branding file uploads ──────────────────────────────────────
        // If any branding file is uploaded, save it and use the resulting path.
        // The text path field is used as a fallback when no file is uploaded.
        $brandingFileFields = [
            'logo_header_file' => 'logo_header',
            'logo_footer_file' => 'logo_footer',
            'logo_file'        => 'logo',
            'favicon_file'     => 'favicon',
        ];

        $uploadedPaths = [];

        foreach ($brandingFileFields as $fileField => $settingKey) {
            $file = $request->file($fileField) ?? [];
            if (!empty($file['name']) && ($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_NO_FILE) {
                // Enable WebP companion and thumbnail for raster branding files (Phase 7c).
                // SVG and ICO are skipped gracefully by GD – no thumb/WebP generated for those.
                $relPath = UploadService::upload($file, 'brand', 'brand', true, true);
                if ($relPath !== null) {
                    $uploadedPaths[$settingKey] = $relPath;
                }
            }
        }

        $fields = [
            // General
            'site_name'        => 'general',
            'site_tagline'     => 'general',
            'contact_email'    => 'general',
            'contact_phone'    => 'general',
            'footer_text'      => 'general',
            'copyright'        => 'general',
            // Fields that support HTML (applied to sanitize_html)
            'footer_text_html' => true,
            'copyright_html'   => true,

            // Branding – legacy single logo + favicon
            'logo'             => 'branding',
            'favicon'          => 'branding',

            // Branding – global header/footer logo system (Phase 6d)
            'logo_header'      => 'branding',
            'logo_footer'      => 'branding',
            'logo_alt'         => 'branding',
            'logo_header_mode' => 'branding',
            'logo_footer_mode' => 'branding',

            // SEO
            'seo_title'        => 'seo',
            'seo_description'  => 'seo',

            // Social
            'social_facebook'  => 'social',
            'social_instagram' => 'social',
            'social_linkedin'  => 'social',
            'social_x'         => 'social',
            'social_youtube'   => 'social',
            'social_discord'   => 'social',
            'social_twitch'    => 'social',
            'social_github'    => 'social',
            'social_tiktok'    => 'social',

            // Language (general settings form)
            'system_language'  => 'general',

            // Display options (general settings form)
            'breadcrumbs_enabled'  => 'general',
            'dark_mode_enabled'    => 'general',
            'search_enabled'       => 'general',
            'search_in_header'     => 'general',

            // Blog options
            'blog_reading_time'    => 'general',
            'blog_toc'             => 'general',
            'blog_related_posts'   => 'general',

            // Extended SEO
            'extended_seo_enabled' => 'seo',

            // Custom CSS/JS
            'custom_css_js_enabled' => 'general',

            // Frontend enhancements
            'sticky_header_enabled'     => 'general',
            'scroll_animations_enabled' => 'general',

            // Content revisions
            'content_revisions_enabled' => 'general',

            // Activity log
            'activity_log_enabled' => 'general',

            // Security & Redirects
            'security_headers_enabled' => 'general',
            'redirect_manager_enabled' => 'general',

            // Content Scheduling
            'content_scheduling_enabled' => 'general',

            // HTTP Cache
            'http_cache_enabled' => 'performance',
            'http_cache_ttl'     => 'performance',

            // Page Cache (B2)
            'page_cache_enabled' => 'performance',
            'page_cache_ttl'     => 'performance',

            // TOTP 2FA (B1)
            'totp_2fa_available' => 'features',

            // Accessibility Audit (B3)
            'accessibility_audit_enabled' => 'features',

            // Schema.org (B4)
            'local_business_enabled' => 'seo',
            'local_business_type'    => 'seo',
            'local_business_street'  => 'seo',
            'local_business_city'    => 'seo',
            'local_business_postal'  => 'seo',
            'local_business_country' => 'seo',
            'local_business_lat'     => 'seo',
            'local_business_lng'     => 'seo',
            'local_business_hours'   => 'seo',
            'faq_schema_enabled'     => 'seo',

            // Asset Minification (B5)
            'asset_minification_enabled' => 'performance',

            // Display: Header / Footer toggles
            'header_show_site_name' => 'branding',
            'footer_show_address'   => 'general',

            // Upload settings
            'upload_allowed_extensions' => 'upload',
            'upload_max_filesize_mb'    => 'upload',
        ];

        // Handle checkbox fields: absent from POST when unchecked → default '0'
        $checkboxFields = ['breadcrumbs_enabled', 'dark_mode_enabled', 'search_enabled', 'search_in_header', 'blog_reading_time', 'blog_toc', 'blog_related_posts', 'extended_seo_enabled', 'custom_css_js_enabled', 'sticky_header_enabled', 'scroll_animations_enabled', 'content_revisions_enabled', 'activity_log_enabled', 'security_headers_enabled', 'redirect_manager_enabled', 'content_scheduling_enabled', 'http_cache_enabled', 'page_cache_enabled', 'totp_2fa_available', 'accessibility_audit_enabled', 'local_business_enabled', 'faq_schema_enabled', 'asset_minification_enabled', 'header_show_site_name', 'footer_show_address'];
        foreach ($checkboxFields as $cbKey) {
            $cbValue = $request->input($cbKey, '0') === '1' ? '1' : '0';
            Setting::set($cbKey, $cbValue, $fields[$cbKey] ?? 'general');
        }

        // Whitelist allowed logo modes to prevent CSS class injection
        $allowedModes = ['original', 'filtered'];

        // Fields that should be sanitized as HTML
        $htmlFields = ['footer_text', 'copyright'];

        foreach ($fields as $key => $group) {
            // Skip internal markers
            if (in_array($key, ['footer_text_html', 'copyright_html'], true)) {
                continue;
            }

            // Skip checkbox fields (already handled above)
            if (in_array($key, $checkboxFields, true)) {
                continue;
            }

            // If a file was uploaded for this key, use the file path
            if (isset($uploadedPaths[$key])) {
                $value = $uploadedPaths[$key];
            } else {
                $value = trim($request->input($key, ''));
            }

            if (in_array($key, ['logo_header_mode', 'logo_footer_mode'], true)) {
                if (!in_array($value, $allowedModes, true)) {
                    $value = 'original';
                }
            }

            // Apply HTML sanitization to designated fields
            if (in_array($key, $htmlFields, true) && $value !== '') {
                $value = sanitize_html($value);
            }

            Setting::set($key, $value, $group);
        }

        // If system_language was submitted, update translator and session immediately
        $submittedLang = trim($request->input('system_language', ''));
        if ($submittedLang !== '' && Translator::isSupported($submittedLang)) {
            if ($this->app->hasService('translator')) {
                $translator = $this->app->service('translator');
                $translator->setLocale($submittedLang);
                $translator->clearCache();
            }
            $this->session()->set('locale', $submittedLang);
        }

        // Admin slug (security feature)
        $adminSlug = trim($request->input('admin_slug', 'admin'));
        $adminSlug = preg_replace('/[^a-z0-9\-]/', '', strtolower($adminSlug));
        if ($adminSlug === '') $adminSlug = 'admin';

        // Prevent conflicts with existing routes
        $reserved = ['api', 'installer', 'blog', 'gallery', 'events', 'download', 'contact', 'search', 'sitemap.xml', 'rss', 'feed'];
        if (in_array($adminSlug, $reserved)) {
            $adminSlug = 'admin'; // Fallback to default
        }

        $oldSlug = admin_slug();
        Setting::set('admin_slug', $adminSlug);

        // Write cache file for maintenance mode (index.php reads this before bootstrap)
        $cacheFile = $this->app->basePath() . '/storage/.admin_slug';
        file_put_contents($cacheFile, $adminSlug);

        // Auto-invalidate page cache when settings change
        $cache = new PageCache($this->app->basePath());
        $cache->clear();

        ActivityLogger::log('update', 'settings', null, 'General settings');
        set_flash('success', __('messages.settings_saved'));

        // Redirect to the NEW admin URL (bypass cached admin_slug() which still holds old value)
        Response::redirect('/' . $adminSlug . '/settings');
    }

    /**
     * POST /admin/settings/clear-page-cache
     */
    public function clearCache(Request $request, array $params = []): void
    {
        $this->validateCsrf();

        $cache   = new PageCache($this->app->basePath());
        $cleared = $cache->clear();

        // Also clear a11y audit cache
        $a11y = $this->app->basePath() . '/storage/cache/a11y_audit.json';
        if (is_file($a11y)) {
            @unlink($a11y);
        }

        ActivityLogger::log('clear_cache', 'system', null, "Page cache cleared ({$cleared} files)");
        set_flash('success', __('messages.cache_cleared', ['count' => $cleared]));
        Response::redirect(admin_url('settings'));
    }

    /**
     * POST /admin/settings/branding/upload
     *
     * AJAX/redirect endpoint for uploading a single branding file from the media
     * picker context. Returns JSON with the resulting path so the frontend can
     * update the hidden field and preview without a full page reload.
     */
    public function uploadBranding(Request $request, array $params = []): void
    {
        $this->validateCsrf();

        $file = $request->file('branding_file') ?? [];

        if (empty($file['name']) || ($file['error'] ?? UPLOAD_ERR_NO_FILE) === UPLOAD_ERR_NO_FILE) {
            Response::json(['ok' => false, 'error' => __('messages.error.file_required')]);
            return;
        }

        // Enable WebP companion and thumbnail for raster branding files (Phase 7c).
        $relPath = UploadService::upload($file, 'brand', 'brand', true, true);

        if ($relPath === null) {
            Response::json(['ok' => false, 'error' => __('messages.error.upload_failed')]);
            return;
        }

        Response::json([
            'ok'   => true,
            'path' => $relPath,
            'url'  => '/uploads/' . ltrim($relPath, '/'),
        ]);
    }

    /**
     * POST /admin/settings/language
     *
     * Switch the admin interface language.
     * Accepts POST with 'language' parameter ('de' or 'en').
     */
    public function language(Request $request, array $params = []): void
    {
        $this->validateCsrf();

        $language = trim($request->input('language', ''));

        // Validate language is supported
        if (!Translator::isSupported($language)) {
            set_flash('error', __('messages.invalid_language'));
            Response::redirect(admin_url('settings'));
            return;
        }

        // Update the system_language setting
        Setting::set('system_language', $language, 'general');

        // Update the translator instance to reflect the new locale
        if ($this->app->hasService('translator')) {
            $translator = $this->app->service('translator');
            $translator->setLocale($language);
            $translator->clearCache();
        }

        // Update session locale so the session override does not persist stale value
        $session = $this->session();
        $session->set('locale', $language);

        set_flash('success', __('messages.language_changed'));
        Response::redirect(admin_url('settings'));
    }
}
