<?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\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' => 'Settings',
            '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',

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

            // Display options (general settings form)
            'breadcrumbs_enabled' => 'general',
        ];

        // Handle checkbox fields: absent from POST when unchecked → default '0'
        $checkboxFields = ['breadcrumbs_enabled'];
        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);
        }

        set_flash('success', __('messages.settings_saved'));
        Response::redirect('/admin/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($_SERVER['HTTP_REFERER'] ?? '/admin/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($_SERVER['HTTP_REFERER'] ?? '/admin/settings');
    }
}
