<?php

namespace App\Http\Controllers;

use App\Models\AppSetting;
use App\Support\WhatsAppMessageCopy;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Storage;

class AppSettingsController extends Controller
{
    /** Coincide con frontend `THEME_CUSTOM_PRIMARY_KEYS`. */
    private const THEME_CUSTOM_PRIMARY_KEYS = [
        '--bg-page', '--bg-device', '--bg-card', '--gold', '--text-main',
        '--text-muted', '--border', '--danger', '--success',
    ];

    /**
     * Return current app branding settings for admin screen.
     */
    public function show()
    {
        return response()->json($this->brandingPayload());
    }

    /**
     * Update business name and optional logo image.
     */
    public function update(Request $request)
    {
        if (! Schema::hasTable('app_settings')) {
            return response()->json([
                'message' => 'Falta ejecutar migraciones en el servidor (tabla app_settings).',
            ], 503);
        }

        $baseRules = [
            'business_name' => 'required|string|max:120',
            'logo' => 'nullable|image|mimes:jpg,jpeg,png,webp|max:2048',
            'background' => 'nullable|image|mimes:jpg,jpeg,png,webp|max:4096',
            'theme_id' => 'nullable|string|in:obsidiana,barberia_calida,azul_noche,alabastro,horizonte,pastel_rosa,lavanda_suave,arena_pastel,custom',
            'theme_custom_vars' => 'nullable|string|max:16000',
            'label_staff_singular' => 'nullable|string|max:40',
            'label_staff_plural' => 'nullable|string|max:40',
            'menu_icon_staff' => 'nullable|string|max:32',
            'menu_icon_services' => 'nullable|string|max:32',
            'calendars_collapsed_default' => 'nullable|boolean',
            'inbox_confirm_actions' => 'nullable|boolean',
            'reminder_minutes_before' => 'nullable|integer|min:1|max:1440',
            'reminder_notify_client' => 'nullable|boolean',
            'reminder_notify_barber' => 'nullable|boolean',
            'reminder_wa_enabled' => 'nullable|boolean',
            'reminder_wa_day_before_enabled' => 'nullable|boolean',
            'reminder_wa_day_before_times' => 'nullable|string|max:200',
            'reminder_wa_day_before_client' => 'nullable|boolean',
            'reminder_wa_day_before_barber' => 'nullable|boolean',
            'reminder_wa_minutes_before' => 'nullable|integer|min:0|max:1440',
            'reminder_wa_minutes_client' => 'nullable|boolean',
            'reminder_wa_minutes_barber' => 'nullable|boolean',
            'wa_include_app_url' => 'nullable|boolean',
            'wa_after_booking' => 'nullable|string|in:text,template,both',
            'admin_notify_wa_browser' => 'nullable|boolean',
            'admin_notify_wa_sound' => 'nullable|boolean',
            'admin_notify_wa_desktop' => 'nullable|boolean',
            /** Solo dígitos (código país + número) para wa.me desde la app cliente; ej. 50688888888 */
            'public_whatsapp_phone' => 'nullable|string|max:32',
        ];
        $waCopyRules = array_fill_keys(WhatsAppMessageCopy::persistedSettingKeys(), 'nullable|string|max:8000');
        $validated = $request->validate(array_merge($baseRules, $waCopyRules));

        AppSetting::setValue('business_name', $validated['business_name']);

        if ($request->has('label_staff_singular')) {
            $s = trim((string) $request->input('label_staff_singular', ''));
            AppSetting::setValue('label_staff_singular', $s !== '' ? $s : 'Profesional');
        }
        if ($request->has('label_staff_plural')) {
            $p = trim((string) $request->input('label_staff_plural', ''));
            AppSetting::setValue('label_staff_plural', $p !== '' ? $p : 'Profesionales');
        }

        if ($request->has('menu_icon_staff')) {
            $v = trim((string) $request->input('menu_icon_staff', ''));
            AppSetting::setValue('menu_icon_staff', $v !== '' ? $v : '💈');
        }
        if ($request->has('menu_icon_services')) {
            $v = trim((string) $request->input('menu_icon_services', ''));
            AppSetting::setValue('menu_icon_services', $v !== '' ? $v : '✂️');
        }

        if ($request->has('calendars_collapsed_default')) {
            AppSetting::setValue('calendars_collapsed_default', $request->boolean('calendars_collapsed_default') ? '1' : '0');
        }
        if ($request->has('inbox_confirm_actions')) {
            AppSetting::setValue('inbox_confirm_actions', $request->boolean('inbox_confirm_actions') ? '1' : '0');
        }
        if ($request->has('reminder_minutes_before')) {
            $m = (int) $request->input('reminder_minutes_before');
            if ($m < 1) {
                $m = 1;
            }
            if ($m > 1440) {
                $m = 1440;
            }
            AppSetting::setValue('reminder_minutes_before', (string) $m);
        }
        if ($request->has('reminder_notify_client')) {
            AppSetting::setValue('reminder_notify_client', $request->boolean('reminder_notify_client') ? '1' : '0');
        }
        if ($request->has('reminder_notify_barber')) {
            AppSetting::setValue('reminder_notify_barber', $request->boolean('reminder_notify_barber') ? '1' : '0');
        }

        if ($request->has('reminder_wa_enabled')) {
            AppSetting::setValue('reminder_wa_enabled', $request->boolean('reminder_wa_enabled') ? '1' : '0');
        }
        if ($request->has('reminder_wa_day_before_enabled')) {
            AppSetting::setValue('reminder_wa_day_before_enabled', $request->boolean('reminder_wa_day_before_enabled') ? '1' : '0');
        }
        if ($request->has('reminder_wa_day_before_times')) {
            AppSetting::setValue(
                'reminder_wa_day_before_times',
                $this->normalizeWaDayBeforeTimesString((string) $request->input('reminder_wa_day_before_times', ''))
            );
        }
        if ($request->has('reminder_wa_day_before_client')) {
            AppSetting::setValue('reminder_wa_day_before_client', $request->boolean('reminder_wa_day_before_client') ? '1' : '0');
        }
        if ($request->has('reminder_wa_day_before_barber')) {
            AppSetting::setValue('reminder_wa_day_before_barber', $request->boolean('reminder_wa_day_before_barber') ? '1' : '0');
        }
        if ($request->has('reminder_wa_minutes_before')) {
            $wm = (int) $request->input('reminder_wa_minutes_before');
            if ($wm < 0) {
                $wm = 0;
            }
            if ($wm > 1440) {
                $wm = 1440;
            }
            AppSetting::setValue('reminder_wa_minutes_before', (string) $wm);
        }
        if ($request->has('reminder_wa_minutes_client')) {
            AppSetting::setValue('reminder_wa_minutes_client', $request->boolean('reminder_wa_minutes_client') ? '1' : '0');
        }
        if ($request->has('reminder_wa_minutes_barber')) {
            AppSetting::setValue('reminder_wa_minutes_barber', $request->boolean('reminder_wa_minutes_barber') ? '1' : '0');
        }

        if ($request->has('wa_include_app_url')) {
            AppSetting::setValue('wa_include_app_url', $request->boolean('wa_include_app_url') ? '1' : '0');
        }
        if ($request->has('wa_after_booking')) {
            $ab = (string) $request->input('wa_after_booking');
            if (in_array($ab, ['text', 'template', 'both'], true)) {
                AppSetting::setValue('wa_after_booking', $ab);
            }
        }
        if ($request->has('admin_notify_wa_browser')) {
            AppSetting::setValue('admin_notify_wa_browser', $request->boolean('admin_notify_wa_browser') ? '1' : '0');
        }
        if ($request->has('admin_notify_wa_sound')) {
            AppSetting::setValue('admin_notify_wa_sound', $request->boolean('admin_notify_wa_sound') ? '1' : '0');
        }
        if ($request->has('admin_notify_wa_desktop')) {
            AppSetting::setValue('admin_notify_wa_desktop', $request->boolean('admin_notify_wa_desktop') ? '1' : '0');
        }
        if ($request->has('public_whatsapp_phone')) {
            $normalized = $this->normalizePublicWhatsappPhone((string) $request->input('public_whatsapp_phone', ''));
            AppSetting::setValue('public_whatsapp_phone', $normalized);
        }
        foreach (WhatsAppMessageCopy::persistedSettingKeys() as $waKey) {
            if ($request->has($waKey)) {
                AppSetting::setValue($waKey, (string) $request->input($waKey));
            }
        }

        if (! empty($validated['theme_id'])) {
            AppSetting::setValue('theme_id', $validated['theme_id']);
        }

        if ($request->has('theme_custom_vars')) {
            $raw = $request->input('theme_custom_vars');
            if ($raw === null || $raw === '') {
                AppSetting::setValue('theme_custom_vars', null);
            } elseif (is_string($raw)) {
                $decoded = json_decode($raw, true);
                if (! is_array($decoded)) {
                    return response()->json(['message' => 'Colores personalizados: JSON inválido.'], 422);
                }
                $sanitized = $this->sanitizeThemeCustomVars($decoded);
                AppSetting::setValue('theme_custom_vars', json_encode($sanitized, JSON_UNESCAPED_UNICODE));
            }
        }

        if ($request->hasFile('logo')) {
            $oldLogoUrl = AppSetting::getValue('logo_url');
            if ($oldLogoUrl && str_starts_with($oldLogoUrl, '/photos/branding/')) {
                $oldPath = ltrim(str_replace('/photos/', '', $oldLogoUrl), '/');
                if ($oldPath !== '') {
                    Storage::disk('photos')->delete($oldPath);
                }
            }

            $extension = strtolower($request->file('logo')->getClientOriginalExtension() ?: 'png');
            $fileName = 'logo-' . time() . '.' . $extension;
            $relativePath = 'branding/' . $fileName;
            Storage::disk('photos')->putFileAs('branding', $request->file('logo'), $fileName);
            AppSetting::setValue('logo_url', '/photos/' . $relativePath);
        }

        $oldBackgroundUrl = AppSetting::getValue('background_url');

        if ($request->boolean('remove_background') && ! $request->hasFile('background')) {
            $this->deleteBrandingFileFromDisk($oldBackgroundUrl);
            AppSetting::setValue('background_url', null);
            $oldBackgroundUrl = null;
        }

        if ($request->hasFile('background')) {
            $this->deleteBrandingFileFromDisk($oldBackgroundUrl);
            $extension = strtolower($request->file('background')->getClientOriginalExtension() ?: 'jpg');
            $fileName = 'background-' . time() . '.' . $extension;
            Storage::disk('photos')->putFileAs('branding', $request->file('background'), $fileName);
            AppSetting::setValue('background_url', '/photos/branding/' . $fileName);
        }

        return response()->json([
            'message' => 'Ajustes actualizados correctamente.',
            'settings' => $this->brandingPayload(),
        ]);
    }

    /**
     * Build one consistent payload for branding values.
     */
    private function brandingPayload(): array
    {
        $waCopy = [];
        foreach (WhatsAppMessageCopy::persistedSettingKeys() as $k) {
            $waCopy[$k] = AppSetting::getValue($k, '');
        }

        return array_merge([
            'business_name' => AppSetting::getValue('business_name', 'Barbería DIAICR'),
            'logo_url' => AppSetting::getValue('logo_url', '/logo.png'),
            'theme_id' => AppSetting::getValue('theme_id', 'obsidiana'),
            'theme_custom_vars' => $this->decodedThemeCustomVars(),
            'background_url' => AppSetting::getValue('background_url'),
            'label_staff_singular' => AppSetting::getValue('label_staff_singular', 'Profesional'),
            'label_staff_plural' => AppSetting::getValue('label_staff_plural', 'Profesionales'),
            'menu_icon_staff' => AppSetting::getValue('menu_icon_staff', '💈'),
            'menu_icon_services' => AppSetting::getValue('menu_icon_services', '✂️'),
            'calendars_collapsed_default' => filter_var(AppSetting::getValue('calendars_collapsed_default', '0'), FILTER_VALIDATE_BOOLEAN),
            'inbox_confirm_actions' => filter_var(AppSetting::getValue('inbox_confirm_actions', '1'), FILTER_VALIDATE_BOOLEAN),
            'reminder_minutes_before' => (int) AppSetting::getValue('reminder_minutes_before', '15'),
            'reminder_notify_client' => filter_var(AppSetting::getValue('reminder_notify_client', '1'), FILTER_VALIDATE_BOOLEAN),
            'reminder_notify_barber' => filter_var(AppSetting::getValue('reminder_notify_barber', '1'), FILTER_VALIDATE_BOOLEAN),
            'reminder_wa_enabled' => filter_var(AppSetting::getValue('reminder_wa_enabled', '1'), FILTER_VALIDATE_BOOLEAN),
            'reminder_wa_day_before_enabled' => filter_var(AppSetting::getValue('reminder_wa_day_before_enabled', '1'), FILTER_VALIDATE_BOOLEAN),
            'reminder_wa_day_before_times' => AppSetting::getValue('reminder_wa_day_before_times', '08:00'),
            'reminder_wa_day_before_client' => filter_var(AppSetting::getValue('reminder_wa_day_before_client', '1'), FILTER_VALIDATE_BOOLEAN),
            'reminder_wa_day_before_barber' => filter_var(AppSetting::getValue('reminder_wa_day_before_barber', '0'), FILTER_VALIDATE_BOOLEAN),
            'reminder_wa_minutes_before' => (int) AppSetting::getValue('reminder_wa_minutes_before', '0'),
            'reminder_wa_minutes_client' => filter_var(AppSetting::getValue('reminder_wa_minutes_client', '1'), FILTER_VALIDATE_BOOLEAN),
            'reminder_wa_minutes_barber' => filter_var(AppSetting::getValue('reminder_wa_minutes_barber', '0'), FILTER_VALIDATE_BOOLEAN),
            'wa_include_app_url' => filter_var(AppSetting::getValue('wa_include_app_url', '1'), FILTER_VALIDATE_BOOLEAN),
            'wa_after_booking' => (string) AppSetting::getValue('wa_after_booking', 'text'),
            'admin_notify_wa_browser' => filter_var(AppSetting::getValue('admin_notify_wa_browser', '1'), FILTER_VALIDATE_BOOLEAN),
            'admin_notify_wa_sound' => filter_var(AppSetting::getValue('admin_notify_wa_sound', '1'), FILTER_VALIDATE_BOOLEAN),
            'admin_notify_wa_desktop' => filter_var(AppSetting::getValue('admin_notify_wa_desktop', '1'), FILTER_VALIDATE_BOOLEAN),
            'public_whatsapp_phone' => AppSetting::getValue('public_whatsapp_phone', ''),
            'wa_copy_defaults' => WhatsAppMessageCopy::defaults(),
        ], $waCopy);
    }

    /**
     * Solo dígitos, longitud típica E.164 sin +: 8–15. Vacío si no es válido.
     */
    private function normalizePublicWhatsappPhone(string $raw): string
    {
        $digits = preg_replace('/\D+/', '', $raw) ?? '';
        if (strlen($digits) < 8 || strlen($digits) > 15) {
            return '';
        }

        return $digits;
    }

    /**
     * Normaliza lista de horarios HH:MM (coma o espacio) para guardar en app_settings.
     */
    private function normalizeWaDayBeforeTimesString(string $raw): string
    {
        $trim = trim($raw);
        if ($trim === '') {
            return '08:00';
        }

        $parts = preg_split('/[\s,]+/', $trim, -1, PREG_SPLIT_NO_EMPTY);
        $out = [];
        foreach ($parts as $p) {
            if (! preg_match('/^(\d{1,2}):(\d{2})$/', $p, $m)) {
                continue;
            }
            $h = (int) $m[1];
            $min = (int) $m[2];
            if ($h < 0 || $h > 23 || $min < 0 || $min > 59) {
                continue;
            }
            $out[] = sprintf('%02d:%02d', $h, $min);
        }

        return $out !== [] ? implode(',', array_unique($out)) : '08:00';
    }

    private function decodedThemeCustomVars(): ?array
    {
        $raw = AppSetting::getValue('theme_custom_vars');
        if ($raw === null || $raw === '') {
            return null;
        }
        $d = json_decode((string) $raw, true);

        return is_array($d) ? $d : null;
    }

    /**
     * Solo claves permitidas y valores tipo color (hex o rgba corto).
     *
     * @param  array<string, mixed>  $input
     * @return array<string, string>
     */
    private function sanitizeThemeCustomVars(array $input): array
    {
        $out = [];
        foreach (self::THEME_CUSTOM_PRIMARY_KEYS as $k) {
            if (! array_key_exists($k, $input)) {
                continue;
            }
            $v = trim((string) $input[$k]);
            if ($v === '' || strlen($v) > 64) {
                continue;
            }
            if (preg_match('/^#[0-9A-Fa-f]{3,8}$/', $v) || preg_match('/^rgba?\(/', $v)) {
                $out[$k] = $v;
            }
        }

        return $out;
    }

    private function deleteBrandingFileFromDisk(?string $publicUrl): void
    {
        if ($publicUrl && str_starts_with($publicUrl, '/photos/branding/')) {
            $relative = ltrim(str_replace('/photos/', '', $publicUrl), '/');
            if ($relative !== '') {
                Storage::disk('photos')->delete($relative);
            }
        }
    }
}
