import { Head } from '@inertiajs/react';
import { useEffect, useMemo, type CSSProperties, type ReactNode } from 'react';
import { buildPalette, sansFont, type Palette } from '@/components/proposal/palette';

export type Brand = {
    name: string; slug: string; logo_url: string | null; phone: string | null; website: string | null;
    colours: { primary: string; secondary: string; background: string; text: string; button: string };
    heading_font: string; body_font: string;
};

export function usePublicTheme(brand: Brand) {
    const p = useMemo(() => buildPalette(brand.colours), [brand.colours]);
    const heading = sansFont(brand.heading_font);
    const body = sansFont(brand.body_font);
    const hf: CSSProperties = { fontFamily: `'${heading}', sans-serif` };
    const fonts = [...new Set([heading, body])].map((f) => `family=${encodeURIComponent(f)}:wght@400;500;600;700`).join('&');
    return { p, hf, body, fonts };
}

/** Client-facing page frame (lead form, review form, reviews page): company branding; compact when embedded. */
export function PublicShell({ brand, title, embed, children, width = 'max-w-xl' }: { brand: Brand; title: string; embed?: boolean; children: (t: { p: Palette; hf: CSSProperties }) => ReactNode; width?: string }) {
    const { p, hf, body, fonts } = usePublicTheme(brand);
    // Embedded in an iframe: tell the parent page our height so it can size the frame (see the embed code).
    useEffect(() => {
        if (embed) { document.body.style.background = 'transparent'; document.documentElement.style.background = 'transparent'; }
        if (!embed || window.parent === window) return;
        const send = () => window.parent.postMessage({ type: 'spin-embed-height', height: document.documentElement.scrollHeight }, '*');
        send();
        const ro = new ResizeObserver(send);
        ro.observe(document.body);
        return () => ro.disconnect();
    }, [embed]);
    return (
        <div className="min-h-screen" style={{ background: embed ? 'transparent' : p.page, color: p.text, fontFamily: `'${body}', sans-serif` }}>
            <Head title={`${title} · ${brand.name}`}>
                <meta name="robots" content="noindex" />
                <link rel="stylesheet" href={`https://fonts.googleapis.com/css2?${fonts}&display=swap`} />
            </Head>
            <main className={`mx-auto w-full ${width} ${embed ? 'px-1 py-2' : 'px-4 py-8 sm:py-12'}`}>
                {!embed && (
                    <header className="mb-6 flex items-center justify-center">
                        {brand.logo_url
                            ? <img src={brand.logo_url} alt={brand.name} className="h-auto max-h-16 w-auto max-w-[230px] object-contain" />
                            : <span className="text-xl font-semibold" style={hf}>{brand.name}</span>}
                    </header>
                )}
                {children({ p, hf })}
                {!embed && (
                    <footer className="mt-8 text-center text-xs" style={{ color: p.muted }}>
                        {brand.name}{brand.phone ? ` · ${brand.phone}` : ''}{brand.website ? <> · <a href={brand.website} className="underline" style={{ color: p.accentInk }}>{brand.website.replace(/^https?:\/\//, '')}</a></> : null}
                    </footer>
                )}
            </main>
        </div>
    );
}

/** Loads Cloudflare Turnstile and renders the (usually invisible) widget; the token lands in a hidden form field. */
export function Turnstile({ siteKey }: { siteKey: string | null }) {
    useEffect(() => {
        if (!siteKey || document.querySelector('script[data-turnstile]')) return;
        const s = document.createElement('script');
        s.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js';
        s.async = true; s.defer = true; s.dataset.turnstile = '1';
        document.head.appendChild(s);
    }, [siteKey]);
    if (!siteKey) return null;
    return <div className="cf-turnstile" data-sitekey={siteKey} data-appearance="interaction-only" />;
}

export function publicInputStyle(p: Palette): CSSProperties {
    return { background: p.bg, color: p.text, borderColor: p.cardLine };
}

/** POSTs a form as multipart with fetch (works in third-party iframes: no cookies needed). */
export async function postForm(url: string, form: HTMLFormElement | FormData): Promise<{ ok: boolean; data: any; errors: Record<string, string> }> {
    const fd = form instanceof FormData ? form : new FormData(form);
    const res = await fetch(url, { method: 'POST', body: fd, headers: { Accept: 'application/json', 'X-Requested-With': 'XMLHttpRequest' }, credentials: 'omit' });
    const text = await res.text();
    const data = text ? (() => { try { return JSON.parse(text); } catch { return null; } })() : null;
    if (res.ok) return { ok: true, data, errors: {} };
    const errors: Record<string, string> = {};
    if (data?.errors) Object.entries(data.errors as Record<string, string[]>).forEach(([k, v]) => { errors[k] = v[0]; });
    else errors.form = data?.message || (res.status === 429 ? 'Too many attempts. Please wait a minute and try again.' : 'Something went wrong. Please try again.');
    return { ok: false, data, errors };
}
