import { Form } from '@inertiajs/react';
import { useEffect, useState  } from 'react';
import type {ReactNode} from 'react';
import ColorPresetPicker from '@/components/branding/color-preset-picker';
import FontSelect from '@/components/branding/font-select';
import LogoUploadField from '@/components/branding/logo-upload-field';
import ThemePreview from '@/components/branding/theme-preview';
import InputError from '@/components/input-error';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { Spinner } from '@/components/ui/spinner';
import { loadPreviewFonts } from '@/lib/branding-preview';
import type {
    BrandingLogoField,
    BrandingPageProps,
    BrandingPreset,
} from '@/types/branding';

type BrandingFormProps = BrandingPageProps & {
    formAction: { action: string; method: 'post' };
    submitLabel: string;
    removeLogoUrl?: (type: BrandingLogoField) => string;
    footer?: ReactNode;
};

const LOGO_FIELDS: { name: BrandingLogoField; label: string; hint: string }[] =
    [
        {
            name: 'logo',
            label: 'Logo',
            hint: 'Shown in the sidebar and header.',
        },
        {
            name: 'logo_dark',
            label: 'Logo for dark mode',
            hint: 'Optional. Defaults to the logo.',
        },
        {
            name: 'icon',
            label: 'Icon',
            hint: 'Square mark for the collapsed sidebar. Optional.',
        },
    ];

export default function BrandingForm({
    branding,
    logos,
    presets,
    fonts,
    logoLimits,
    formAction,
    submitLabel,
    removeLogoUrl,
    footer,
}: BrandingFormProps) {
    const [presetKey, setPresetKey] = useState<string | null>(branding.preset);
    const [primary, setPrimary] = useState(branding.primary_color);
    const [accent, setAccent] = useState(branding.accent_color ?? primary);
    const [headingFont, setHeadingFont] = useState(branding.heading_font);
    const [bodyFont, setBodyFont] = useState(branding.body_font);
    const [logoPreviewUrl, setLogoPreviewUrl] = useState<string | null>(null);

    useEffect(() => {
        loadPreviewFonts(fonts);
    }, [fonts]);

    const fontFamily = (fontKey: string): string =>
        fonts.find((font) => font.key === fontKey)?.family ?? fontKey;

    const acceptedExtensions = logoLimits.mimes
        .map((mime) => `.${mime}`)
        .join(',');
    const sizeHint = `${logoLimits.minPixels}-${logoLimits.maxPixels}px, up to ${Math.round(logoLimits.maxKilobytes / 1024)} MB. ${logoLimits.mimes.join(', ').toUpperCase()}.`;

    const selectPreset = (preset: BrandingPreset): void => {
        setPresetKey(preset.key);
        setPrimary(preset.primary);
        setAccent(preset.accent);
    };

    return (
        <Form
            {...formAction}
            disableWhileProcessing
            className="grid gap-10 lg:grid-cols-[minmax(0,1fr)_minmax(0,1fr)]"
        >
            {({ processing, errors }) => (
                <>
                    <div className="grid gap-8">
                        <input
                            type="hidden"
                            name="preset"
                            value={presetKey ?? ''}
                        />

                        <section className="grid gap-4">
                            <h3 className="text-sm font-medium">Colors</h3>
                            <ColorPresetPicker
                                presets={presets}
                                selectedPresetKey={presetKey}
                                primary={primary}
                                accent={accent}
                                errors={errors}
                                onPresetSelect={selectPreset}
                                onPrimaryChange={(color) => {
                                    setPrimary(color);
                                    setPresetKey(null);
                                }}
                                onAccentChange={(color) => {
                                    setAccent(color);
                                    setPresetKey(null);
                                }}
                            />
                        </section>

                        <section className="grid gap-4">
                            <h3 className="text-sm font-medium">Fonts</h3>
                            <div className="grid gap-4 sm:grid-cols-2">
                                <div className="grid gap-2">
                                    <Label htmlFor="heading_font">
                                        Headings
                                    </Label>
                                    <FontSelect
                                        id="heading_font"
                                        name="heading_font"
                                        value={headingFont}
                                        fonts={fonts}
                                        onValueChange={setHeadingFont}
                                    />
                                    <InputError message={errors.heading_font} />
                                </div>

                                <div className="grid gap-2">
                                    <Label htmlFor="body_font">Body text</Label>
                                    <FontSelect
                                        id="body_font"
                                        name="body_font"
                                        value={bodyFont}
                                        fonts={fonts}
                                        onValueChange={setBodyFont}
                                    />
                                    <InputError message={errors.body_font} />
                                </div>
                            </div>
                        </section>

                        <section className="grid gap-6">
                            <h3 className="text-sm font-medium">Logos</h3>
                            {LOGO_FIELDS.map((field) => (
                                <LogoUploadField
                                    key={field.name}
                                    name={field.name}
                                    label={field.label}
                                    hint={`${field.hint} ${sizeHint}`}
                                    accept={acceptedExtensions}
                                    currentUrl={logos[field.name]}
                                    removeUrl={removeLogoUrl?.(field.name)}
                                    error={errors[field.name]}
                                    onPreviewChange={
                                        field.name === 'logo'
                                            ? setLogoPreviewUrl
                                            : undefined
                                    }
                                />
                            ))}
                        </section>

                        <div className="flex items-center justify-between gap-4">
                            <Button type="submit">
                                {processing && <Spinner />}
                                {submitLabel}
                            </Button>
                            {footer}
                        </div>
                    </div>

                    <div className="lg:sticky lg:top-6 lg:self-start">
                        <p className="mb-3 text-sm font-medium">Preview</p>
                        <ThemePreview
                            primary={primary}
                            accent={accent}
                            headingFamily={fontFamily(headingFont)}
                            bodyFamily={fontFamily(bodyFont)}
                            logoUrl={logoPreviewUrl ?? logos.logo}
                        />
                    </div>
                </>
            )}
        </Form>
    );
}
