<?php

declare(strict_types=1);

namespace Admin\Controllers;

/**
 * Admin Settings Controller
 *
 * Manages site-wide settings stored as key-value pairs,
 * grouped by category (General, Stats, Social Media, Offer Popup).
 * Supports text, number, url, email, textarea, select, and file field types.
 */
class AdminSettingsController extends AdminController
{
    /**
     * Display the settings form.
     *
     * @param array<string, string> $params Route parameters
     * @return void
     */
    public function index(array $params = []): void
    {
        requireAdmin();

        // Read from BOTH column schemas (new setting_key/setting_value AND
        // legacy key_name/value) so settings saved in either schema are visible
        // in the admin form. This is consistent with App\Models\Setting::getAll().
        $settings = [];

        try {
            $stmt = $this->db->query('SELECT `setting_key`, `setting_value` FROM `settings` WHERE `setting_key` IS NOT NULL AND `setting_key` != \'\'');
            $rows = $stmt->fetchAll() ?: [];
            foreach ($rows as $row) {
                $settings[$row['setting_key']] = $row['setting_value'];
            }
        } catch (\Throwable $e) {
            // Fall through to legacy schema
        }

        try {
            $stmt2 = $this->db->query('SELECT `key_name`, `value` FROM `settings` WHERE `key_name` IS NOT NULL AND `key_name` != \'\'');
            $rows2 = $stmt2->fetchAll() ?: [];
            foreach ($rows2 as $row) {
                if (!isset($settings[$row['key_name']]) || $settings[$row['key_name']] === '') {
                    $settings[$row['key_name']] = $row['value'];
                }
            }
        } catch (\Throwable $e) {
            // Fall through
        }

        // Define setting groups for the form
        $settingGroups = [
            'General' => [
                'site_name'     => ['label' => 'Site Name', 'type' => 'text'],
                'site_tagline'  => ['label' => 'Site Tagline', 'type' => 'text'],
                'site_logo'     => ['label' => 'Site Logo', 'type' => 'file'],
                'affiliation_logo' => ['label' => 'Affiliation Logo', 'type' => 'file'],
                'site_email'    => ['label' => 'Site Email', 'type' => 'email'],
                'site_phone'    => ['label' => 'Site Phone', 'type' => 'text'],
                'site_address'  => ['label' => 'Site Address', 'type' => 'textarea'],
                'footer_text'   => ['label' => 'Footer Text', 'type' => 'text'],
                'contact_email' => ['label' => 'Contact Email', 'type' => 'email'],
                'maintenance_mode' => ['label' => 'Maintenance Mode', 'type' => 'select', 'options' => ['0' => 'Off', '1' => 'On']],
            ],
            'Stats' => [
                'stat_total_students'  => ['label' => 'Total Students', 'type' => 'number'],
                'stat_total_courses'   => ['label' => 'Total Courses', 'type' => 'number'],
                'stat_total_branches'  => ['label' => 'Total Branches', 'type' => 'number'],
                'stat_years_experience' => ['label' => 'Years of Experience', 'type' => 'number'],
            ],
            'Social Media' => [
                'social_facebook'  => ['label' => 'Facebook URL', 'type' => 'url'],
                'social_twitter'   => ['label' => 'Twitter/X URL', 'type' => 'url'],
                'social_youtube'   => ['label' => 'YouTube URL', 'type' => 'url'],
                'social_instagram' => ['label' => 'Instagram URL', 'type' => 'url'],
                'social_linkedin'  => ['label' => 'LinkedIn URL', 'type' => 'url'],
            ],
            'WhatsApp Floating Button' => [
                'whatsapp_enabled' => ['label' => 'Enable WhatsApp Button', 'type' => 'select', 'options' => ['0' => 'Disabled', '1' => 'Enabled']],
                'whatsapp_number'  => ['label' => 'WhatsApp Number (with country code, digits only)', 'type' => 'text'],
                'whatsapp_message' => ['label' => 'Pre-filled Message', 'type' => 'textarea'],
            ],
            'Live Chat Widget' => [
                'chat_enabled'         => ['label' => 'Enable Live Chat', 'type' => 'select', 'options' => ['0' => 'Disabled', '1' => 'Enabled']],
                'chat_title'           => ['label' => 'Chat Header Title', 'type' => 'text'],
                'chat_subtitle'        => ['label' => 'Chat Header Subtitle', 'type' => 'text'],
                'chat_welcome_message' => ['label' => 'Auto-Welcome Message (sent on first connect)', 'type' => 'textarea'],
            ],
            'Homepage Countdown Timer' => [
                'countdown_enabled'      => ['label' => 'Enable Manual Countdown', 'type' => 'select', 'options' => ['0' => 'Disabled (use batch show_countdown instead)', '1' => 'Enabled (use settings below)']],
                'countdown_title'        => ['label' => 'Countdown Title', 'type' => 'text'],
                'countdown_subtitle'     => ['label' => 'Countdown Subtitle', 'type' => 'text'],
                'countdown_target_date'  => ['label' => 'Target Date & Time', 'type' => 'datetime-local'],
                'countdown_button_text'  => ['label' => 'Button Text', 'type' => 'text'],
                'countdown_button_url'   => ['label' => 'Button URL', 'type' => 'url'],
            ],
            'Offer Popup' => [
                'offer_popup_enabled'     => ['label' => 'Enable Offer Popup', 'type' => 'select', 'options' => ['0' => 'Disabled', '1' => 'Enabled']],
                'offer_popup_title'       => ['label' => 'Popup Title', 'type' => 'text'],
                'offer_popup_description' => ['label' => 'Popup Description', 'type' => 'textarea'],
                'offer_popup_image'       => ['label' => 'Popup Image', 'type' => 'file'],
                'offer_popup_link'        => ['label' => 'Popup Link URL', 'type' => 'url'],
                'offer_popup_link_text'   => ['label' => 'Popup Button Text', 'type' => 'text'],
            ],
        ];

        $this->adminView('settings', [
            'title'         => 'Site Settings',
            'currentPage'   => 'settings',
            'settings'      => $settings,
            'settingGroups' => $settingGroups,
        ]);
    }

    /**
     * Update all settings at once.
     *
     * Handles both text-based fields and file uploads (for site_logo, affiliation_logo, offer_popup_image).
     *
     * @param array<string, string> $params Route parameters
     * @return void
     */
    public function update(array $params = []): void
    {
        requireAdmin();
        $this->validateCsrf();

        $allowedKeys = [
            'site_name', 'site_tagline', 'site_logo', 'affiliation_logo',
            'site_email', 'site_phone', 'site_address',
            'footer_text', 'contact_email', 'maintenance_mode',
            'stat_total_students', 'stat_total_courses', 'stat_total_branches', 'stat_years_experience',
            'social_facebook', 'social_twitter', 'social_youtube', 'social_instagram', 'social_linkedin',
            'whatsapp_enabled', 'whatsapp_number', 'whatsapp_message',
            'chat_enabled', 'chat_title', 'chat_subtitle', 'chat_welcome_message',
            'countdown_enabled', 'countdown_title', 'countdown_subtitle',
            'countdown_target_date', 'countdown_button_text', 'countdown_button_url',
            'offer_popup_enabled', 'offer_popup_title', 'offer_popup_description',
            'offer_popup_image', 'offer_popup_link', 'offer_popup_link_text',
        ];

        $fileKeys = ['site_logo', 'affiliation_logo', 'offer_popup_image'];

        $updated = 0;

        foreach ($allowedKeys as $key) {
            // Handle file uploads separately
            if (in_array($key, $fileKeys, true)) {
                $filePath = $this->handleImageUpload($key, 'settings');
                if ($filePath !== null) {
                    // Delete the old image file if one exists
                    $oldStmt = $this->db->prepare(
                        'SELECT `setting_value` FROM `settings` WHERE `setting_key` = :key LIMIT 1'
                    );
                    $oldStmt->execute([':key' => $key]);
                    $oldPath = $oldStmt->fetchColumn();
                    if ($oldPath && $oldPath !== $filePath) {
                        $this->deleteImageFile((string) $oldPath);
                    }

                    $stmt = $this->db->prepare(
                        'INSERT INTO `settings` (`key_name`, `value`, `setting_key`, `setting_value`)
                         VALUES (:key, :value, :key2, :value2)
                         ON DUPLICATE KEY UPDATE `setting_value` = :value3, `value` = :value4'
                    );

                    $stmt->execute([
                        ':key'    => $key,
                        ':value'  => $filePath,
                        ':key2'   => $key,
                        ':value2' => $filePath,
                        ':value3' => $filePath,
                        ':value4' => $filePath,
                    ]);

                    // Also copy site_logo to images/logo.png as a reliable fallback
                    if ($key === 'site_logo') {
                        $this->syncLogoToDefault($filePath);
                    }

                    $updated++;
                }
                continue;
            }

            if (!isset($_POST[$key])) {
                continue;
            }

            $value = sanitize($_POST[$key]);

            // Use INSERT ... ON DUPLICATE KEY UPDATE for upsert
            // Write to BOTH key_name/value AND setting_key/setting_value
            // to avoid UNIQUE constraint collisions on key_name=''
            $stmt = $this->db->prepare(
                'INSERT INTO `settings` (`key_name`, `value`, `setting_key`, `setting_value`)
                 VALUES (:key, :value, :key2, :value2)
                 ON DUPLICATE KEY UPDATE `setting_value` = :value3, `value` = :value4'
            );

            $stmt->execute([
                ':key'    => $key,
                ':value'  => $value,
                ':key2'   => $key,
                ':value2' => $value,
                ':value3' => $value,
                ':value4' => $value,
            ]);

            $updated++;
        }

        flash('success', "Settings updated successfully. ({$updated} settings saved)");
        redirect(BASE_PATH . '/admin/settings');
    }

    /**
     * Copy the uploaded logo file to images/logo.png as a reliable fallback.
     *
     * This ensures the header always has the latest logo in images/logo.png,
     * even if the settings data isn't loaded on some pages.
     *
     * @param string $uploadedPath The relative path of the uploaded file (e.g. 'uploads/settings/img_xxx.jpg')
     * @return void
     */
    private function syncLogoToDefault(string $uploadedPath): void
    {
        $sourceFile = PUBLIC_ROOT . '/' . $uploadedPath;
        $destFile   = PUBLIC_ROOT . '/images/logo.png';

        if (!file_exists($sourceFile)) {
            error_log("syncLogoToDefault: Source file not found: {$sourceFile}");
            return;
        }

        // If the uploaded file is already a PNG, just copy it
        // Otherwise, convert to PNG using GD (if available)
        $mimeType = mime_content_type($sourceFile);

        if ($mimeType === 'image/png') {
            if (!copy($sourceFile, $destFile)) {
                error_log("syncLogoToDefault: Failed to copy {$sourceFile} to {$destFile}");
            }
        } elseif (extension_loaded('gd') || extension_loaded('imagick')) {
            // Convert to PNG using GD
            $image = null;
            switch ($mimeType) {
                case 'image/jpeg':
                    $image = imagecreatefromjpeg($sourceFile);
                    break;
                case 'image/gif':
                    $image = imagecreatefromgif($sourceFile);
                    break;
                case 'image/webp':
                    $image = imagecreatefromwebp($sourceFile);
                    break;
                case 'image/png':
                    $image = imagecreatefrompng($sourceFile);
                    break;
            }

            if ($image !== false && $image !== null) {
                // Preserve transparency for PNG output
                imagealphablending($image, false);
                imagesavealpha($image, true);
                if (!imagepng($image, $destFile, 9)) {
                    error_log("syncLogoToDefault: Failed to write PNG to {$destFile}");
                }
                imagedestroy($image);
            } else {
                // GD conversion failed — just copy the original file
                if (!copy($sourceFile, $destFile)) {
                    error_log("syncLogoToDefault: GD failed and copy also failed for {$sourceFile}");
                }
            }
        } else {
            // No GD — just copy the original file (browsers handle non-png too)
            if (!copy($sourceFile, $destFile)) {
                error_log("syncLogoToDefault: No GD, copy failed for {$sourceFile}");
            }
        }
    }
}
