import { Head, Link, useForm, usePage } from '@inertiajs/react';
import type { FormEvent, MouseEvent } from 'react';
import { useEffect, useMemo, useState } from 'react';
import '../../../css/theme-editor.css';

type ThemePreset = {
    id: string;
    name: string;
    description: string;
    colors: { primary: string; accent: string; background: string; surface: string; text: string };
    headingFont: string;
    bodyFont: string;
    borderRadius: number;
};

type FontOption = {
    id: string;
    label: string;
    fontFamily: string;
    category: 'serif' | 'sans-serif';
};

type ThemeSettings = {
    presetId: string | null;
    primaryColor: string;
    accentColor: string;
    backgroundColor: string;
    surfaceColor: string;
    textColor: string;
    headingFont: string;
    bodyFont: string;
    borderRadius: number;
    updatedAt: string | null;
};

type PageProps = {
    wedding: { name: string };
    settings: ThemeSettings;
    presets: ThemePreset[];
    fonts: FontOption[];
    flash: { success: string | null };
    errors: Record<string, string>;
};

type ThemeForm = {
    preset_id: string | null;
    primary_color: string;
    accent_color: string;
    background_color: string;
    surface_color: string;
    text_color: string;
    heading_font: string;
    body_font: string;
    border_radius: number;
};

type ColorKey = 'primary_color' | 'accent_color' | 'background_color' | 'surface_color' | 'text_color';
type PreviewSize = 'desktop' | 'mobile';

const HEX_COLOR = /^#[0-9a-fA-F]{6}$/;
const FALLBACK_COLOR = '#879b82';
const colorFields: Array<{ key: ColorKey; label: string; description: string }> = [
    { key: 'primary_color', label: 'Markenfarbe', description: 'Buttons, Links und wichtige Akzente' },
    { key: 'accent_color', label: 'Akzentfarbe', description: 'Sanfte Hervorhebungen und Dekoration' },
    { key: 'background_color', label: 'Seitenhintergrund', description: 'Grundfläche des Hochzeitsbereichs' },
    { key: 'surface_color', label: 'Kartenfarbe', description: 'Einladungen und Informationsflächen' },
    { key: 'text_color', label: 'Textfarbe', description: 'Fließtext und zentrale Informationen' },
];

const initialForm = (settings: ThemeSettings): ThemeForm => ({
    preset_id: settings.presetId,
    primary_color: settings.primaryColor,
    accent_color: settings.accentColor,
    background_color: settings.backgroundColor,
    surface_color: settings.surfaceColor,
    text_color: settings.textColor,
    heading_font: settings.headingFont,
    body_font: settings.bodyFont,
    border_radius: settings.borderRadius,
});

const colorToRgb = (color: string) => {
    if (!HEX_COLOR.test(color)) return null;
    return {
        red: Number.parseInt(color.slice(1, 3), 16),
        green: Number.parseInt(color.slice(3, 5), 16),
        blue: Number.parseInt(color.slice(5, 7), 16),
    };
};

const relativeLuminance = (color: string) => {
    const rgb = colorToRgb(color);
    if (!rgb) return null;
    const channel = (value: number) => {
        const normalized = value / 255;
        return normalized <= 0.03928 ? normalized / 12.92 : ((normalized + 0.055) / 1.055) ** 2.4;
    };
    return 0.2126 * channel(rgb.red) + 0.7152 * channel(rgb.green) + 0.0722 * channel(rgb.blue);
};

const contrastRatio = (foreground: string, background: string) => {
    const foregroundLuminance = relativeLuminance(foreground);
    const backgroundLuminance = relativeLuminance(background);
    if (foregroundLuminance === null || backgroundLuminance === null) return null;
    return (Math.max(foregroundLuminance, backgroundLuminance) + 0.05)
        / (Math.min(foregroundLuminance, backgroundLuminance) + 0.05);
};

export default function ThemeEditor() {
    const { wedding, settings, presets, fonts, flash, errors } = usePage<PageProps>().props;
    const initial = initialForm(settings);
    const form = useForm<ThemeForm>(initial);
    const [savedSettings, setSavedSettings] = useState<ThemeForm>(initial);
    const [previewSize, setPreviewSize] = useState<PreviewSize>('desktop');
    const [colorErrors, setColorErrors] = useState<Partial<Record<ColorKey, string>>>({});

    const isDirty = (Object.keys(savedSettings) as Array<keyof ThemeForm>)
        .some((key) => form.data[key] !== savedSettings[key]);
    const selectedPresetId = form.data.preset_id;
    const colorValue = (key: ColorKey) => HEX_COLOR.test(form.data[key]) ? form.data[key] : FALLBACK_COLOR;
    const headingFont = fonts.find((font) => font.id === form.data.heading_font);
    const bodyFont = fonts.find((font) => font.id === form.data.body_font);
    const generalError = errors.theme ?? errors.design ?? errors.general;

    const contrastWarnings = useMemo(() => {
        const warnings: string[] = [];
        const bodyContrast = contrastRatio(form.data.text_color, form.data.surface_color);
        const pageContrast = contrastRatio(form.data.text_color, form.data.background_color);
        const buttonContrast = contrastRatio('#ffffff', form.data.primary_color);
        if (bodyContrast !== null && bodyContrast < 4.5) warnings.push('Text und Kartenfarbe sind zu ähnlich. Fließtext könnte schwer lesbar sein.');
        if (pageContrast !== null && pageContrast < 4.5) warnings.push('Text hebt sich auf dem Seitenhintergrund nicht deutlich genug ab.');
        if (buttonContrast !== null && buttonContrast < 4.5) warnings.push('Weiße Buttonbeschriftungen haben auf der Markenfarbe wenig Kontrast.');
        return warnings;
    }, [form.data.background_color, form.data.primary_color, form.data.surface_color, form.data.text_color]);

    useEffect(() => {
        const warnBeforeUnload = (event: BeforeUnloadEvent) => {
            if (!isDirty) return;
            event.preventDefault();
            event.returnValue = '';
        };
        window.addEventListener('beforeunload', warnBeforeUnload);
        return () => window.removeEventListener('beforeunload', warnBeforeUnload);
    }, [isDirty]);

    const setCustomData = <K extends keyof ThemeForm>(key: K, value: ThemeForm[K]) => {
        form.setData({ ...form.data, preset_id: null, [key]: value });
    };

    const updateColor = (key: ColorKey, value: string) => {
        setColorErrors((current) => ({ ...current, [key]: undefined }));
        setCustomData(key, value);
    };

    const applyPreset = (preset: ThemePreset) => {
        setColorErrors({});
        form.clearErrors();
        form.setData({
            preset_id: preset.id,
            primary_color: preset.colors.primary,
            accent_color: preset.colors.accent,
            background_color: preset.colors.background,
            surface_color: preset.colors.surface,
            text_color: preset.colors.text,
            heading_font: preset.headingFont,
            body_font: preset.bodyFont,
            border_radius: preset.borderRadius,
        });
    };

    const submit = (submitEvent: FormEvent<HTMLFormElement>) => {
        submitEvent.preventDefault();
        if (form.processing) return;
        const nextColorErrors: Partial<Record<ColorKey, string>> = {};
        colorFields.forEach(({ key }) => {
            if (!HEX_COLOR.test(form.data[key])) nextColorErrors[key] = 'Bitte gib einen sechsstelligen Hex-Wert wie #879b82 ein.';
        });
        if (Object.keys(nextColorErrors).length > 0) {
            setColorErrors(nextColorErrors);
            return;
        }
        setColorErrors({});
        form.put('/design', {
            preserveScroll: true,
            onSuccess: () => setSavedSettings({ ...form.data }),
        });
    };

    const handleBack = (clickEvent: MouseEvent<Element>) => {
        if (isDirty && !window.confirm('Es gibt ungespeicherte Designänderungen. Möchtest du die Seite wirklich verlassen?')) {
            clickEvent.preventDefault();
        }
    };

    return (
        <>
            <Head title="Design gestalten" />
            <main className="theme-editor-shell">
                <nav className="theme-editor-nav" aria-label="Bereichsnavigation">
                    <div><span className="theme-editor-eyebrow">{wedding.name}</span><strong>Design-Studio</strong></div>
                    <Link className="theme-editor-secondary" href="/dashboard" onClick={handleBack}>Zurück zum Dashboard</Link>
                </nav>

                <header className="theme-editor-header">
                    <div><span className="theme-editor-eyebrow">Erscheinungsbild</span><h1>Hochzeitsdesign gestalten</h1></div>
                    <div className="theme-editor-save-state" aria-live="polite">
                        <span className={isDirty ? 'is-dirty' : 'is-saved'}>{isDirty ? 'Ungespeicherte Änderungen' : 'Alles gespeichert'}</span>
                        {settings.updatedAt && <small>Zuletzt aktualisiert: {new Intl.DateTimeFormat('de-DE', { dateStyle: 'medium', timeStyle: 'short' }).format(new Date(settings.updatedAt))}</small>}
                    </div>
                </header>

                {flash.success && <div className="alert theme-editor-success" role="status">{flash.success}</div>}
                {generalError && <div className="alert alert-danger theme-editor-page-alert" role="alert">{generalError}</div>}

                <form aria-busy={form.processing} noValidate onSubmit={submit}>
                    <div className="theme-editor-layout">
                        <div className="theme-editor-controls">
                            <section className="theme-editor-panel" aria-labelledby="theme-presets-title">
                                <div className="theme-editor-section-heading"><div><span className="theme-editor-eyebrow">Schnellstart</span><h2 id="theme-presets-title">Designvorlagen</h2></div></div>
                                <p className="theme-editor-copy">Eine Vorlage übernimmt Farben, Schriften und Ecken zunächst nur in dieser Ansicht.</p>
                                {presets.length === 0 ? <p className="theme-editor-empty">Zurzeit stehen keine Designvorlagen zur Verfügung.</p> : (
                                    <div className="theme-editor-preset-list">
                                        {presets.map((preset) => {
                                            const inputId = `theme-preset-${preset.id}`;
                                            return <label className={selectedPresetId === preset.id ? 'is-selected' : ''} htmlFor={inputId} key={preset.id}>
                                                <input checked={selectedPresetId === preset.id} id={inputId} name="theme-preset" onChange={() => applyPreset(preset)} type="radio" />
                                                <span className="theme-editor-preset-swatches" aria-hidden="true">{Object.values(preset.colors).map((color, index) => <i key={index} style={{ backgroundColor: HEX_COLOR.test(color) ? color : FALLBACK_COLOR }} />)}</span>
                                                <span className="theme-editor-preset-copy"><strong>{preset.name}</strong><small>{preset.description}</small></span>
                                                <span className="theme-editor-preset-check" aria-hidden="true">✓</span>
                                            </label>;
                                        })}
                                    </div>
                                )}
                            </section>

                            <section className="theme-editor-panel" aria-labelledby="theme-colors-title">
                                <div className="theme-editor-section-heading"><div><span className="theme-editor-eyebrow">Farbwelt</span><h2 id="theme-colors-title">Farben abstimmen</h2></div></div>
                                <div className="theme-editor-color-list">
                                    {colorFields.map((field) => {
                                        const backendError = form.errors[field.key];
                                        const fieldError = colorErrors[field.key] || backendError;
                                        return <div className="theme-editor-color-row" key={field.key}>
                                            <div><label htmlFor={`${field.key}-text`}>{field.label}</label><small>{field.description}</small></div>
                                            <input aria-label={`${field.label} auswählen`} onChange={(event) => updateColor(field.key, event.target.value)} type="color" value={colorValue(field.key)} />
                                            <div><input aria-invalid={Boolean(fieldError)} className={`form-control${fieldError ? ' is-invalid' : ''}`} id={`${field.key}-text`} onChange={(event) => updateColor(field.key, event.target.value)} spellCheck={false} value={form.data[field.key]} />{fieldError && <div className="invalid-feedback">{fieldError}</div>}</div>
                                        </div>;
                                    })}
                                </div>
                                {contrastWarnings.length > 0 ? <div className="theme-editor-contrast-warning" role="status"><strong>Kontrast prüfen</strong><ul>{contrastWarnings.map((warning) => <li key={warning}>{warning}</li>)}</ul></div> : <div className="theme-editor-contrast-ok" role="status">Die wichtigsten Textkontraste sind gut unterscheidbar.</div>}
                            </section>

                            <section className="theme-editor-panel" aria-labelledby="theme-typography-title">
                                <div className="theme-editor-section-heading"><div><span className="theme-editor-eyebrow">Details</span><h2 id="theme-typography-title">Schriften &amp; Ecken</h2></div></div>
                                <div className="theme-editor-font-grid">
                                    <div><label className="form-label" htmlFor="heading-font">Überschriftenschrift</label><select className={`form-select${form.errors.heading_font ? ' is-invalid' : ''}`} id="heading-font" onChange={(event) => setCustomData('heading_font', event.target.value)} value={form.data.heading_font}>{fonts.map((font) => <option key={font.id} value={font.id}>{font.label} · {font.category === 'serif' ? 'Serif' : 'Sans Serif'}</option>)}</select>{form.errors.heading_font && <div className="invalid-feedback">{form.errors.heading_font}</div>}</div>
                                    <div><label className="form-label" htmlFor="body-font">Fließtextschrift</label><select className={`form-select${form.errors.body_font ? ' is-invalid' : ''}`} id="body-font" onChange={(event) => setCustomData('body_font', event.target.value)} value={form.data.body_font}>{fonts.map((font) => <option key={font.id} value={font.id}>{font.label} · {font.category === 'serif' ? 'Serif' : 'Sans Serif'}</option>)}</select>{form.errors.body_font && <div className="invalid-feedback">{form.errors.body_font}</div>}</div>
                                </div>
                                {fonts.length === 0 && <p className="theme-editor-empty">Es wurden keine verfügbaren Schriften übergeben.</p>}
                                <div className="theme-editor-radius-field"><div><label htmlFor="border-radius">Eckenradius</label><output htmlFor="border-radius">{form.data.border_radius} px</output></div><input aria-valuetext={`${form.data.border_radius} Pixel`} id="border-radius" max={32} min={0} onChange={(event) => setCustomData('border_radius', Number(event.target.value))} step={1} type="range" value={form.data.border_radius} /><div aria-hidden="true"><span>Eckig</span><span>Sehr rund</span></div>{form.errors.border_radius && <p className="theme-editor-field-error">{form.errors.border_radius}</p>}</div>
                            </section>
                        </div>

                        <aside className="theme-editor-preview-panel" aria-labelledby="theme-preview-title">
                            <div className="theme-editor-section-heading"><div><span className="theme-editor-eyebrow">Live-Vorschau</span><h2 id="theme-preview-title">So wirkt euer Design</h2></div></div>
                            <div className="theme-editor-preview-switch" aria-label="Vorschaugröße" role="group"><button aria-pressed={previewSize === 'desktop'} className={previewSize === 'desktop' ? 'is-active' : ''} onClick={() => setPreviewSize('desktop')} type="button">Desktop</button><button aria-pressed={previewSize === 'mobile'} className={previewSize === 'mobile' ? 'is-active' : ''} onClick={() => setPreviewSize('mobile')} type="button">Mobil</button></div>
                            <div className={`theme-editor-preview-frame is-${previewSize}`}>
                                <div className="theme-editor-preview-canvas" style={{ backgroundColor: colorValue('background_color'), color: colorValue('text_color'), fontFamily: bodyFont?.fontFamily ?? 'system-ui, sans-serif' }}>
                                    <article style={{ backgroundColor: colorValue('surface_color'), borderRadius: `${form.data.border_radius}px` }}>
                                        <span style={{ color: colorValue('primary_color') }}>Persönliche Einladung</span>
                                        <h3 style={{ color: colorValue('primary_color'), fontFamily: headingFont?.fontFamily ?? 'Georgia, serif' }}>{wedding.name}</h3>
                                        <div className="theme-editor-preview-ornament" style={{ color: colorValue('accent_color') }}>◇</div>
                                        <p>Wir freuen uns darauf, diesen besonderen Tag gemeinsam mit euch zu feiern.</p>
                                        <div className="theme-editor-preview-actions"><button style={{ backgroundColor: colorValue('primary_color'), borderRadius: `${form.data.border_radius}px` }}>Ich bin dabei</button><button style={{ borderColor: colorValue('primary_color'), borderRadius: `${form.data.border_radius}px`, color: colorValue('primary_color') }}>Mehr erfahren</button></div>
                                        <aside style={{ backgroundColor: colorValue('accent_color'), borderRadius: `${form.data.border_radius}px` }}><strong>Gut zu wissen</strong><span>Alle wichtigen Informationen findet ihr in eurem geschützten Hochzeitsbereich.</span></aside>
                                    </article>
                                </div>
                            </div>
                            <p className="theme-editor-preview-note">Die Vorschau verwendet ausschließlich lokale Systemschriften und lädt keine externen Ressourcen.</p>
                            <button className="theme-editor-primary" disabled={form.processing} type="submit">{form.processing ? <><span className="spinner-border spinner-border-sm" aria-hidden="true" /> Design wird gespeichert …</> : 'Design speichern'}</button>
                            {form.processing && <p className="theme-editor-saving" role="status">Eure Einstellungen werden übertragen.</p>}
                        </aside>
                    </div>
                </form>
            </main>
        </>
    );
}
