import { Button, Textarea } from '@/Components/ui';
import { csrfHeaders } from '@/admin/settings/types';
import { AlertTriangle, CheckCircle2 } from 'lucide-react';
import { useState } from 'react';

export type ScriptsValue = {
    version: number;
    head: string;
    body: string;
    enabled: boolean;
};

type Props = {
    initial: ScriptsValue;
};

/**
 * Admin editor for site-wide custom analytics scripts (head + body slots).
 * Pasted vendor snippets (gtag, FB Pixel, Hotjar, Intercom, Plausible,
 * Umami, etc.) emit verbatim on the public marketing surface only.
 * Admin / editor / auth pages never include the scripts and stay on the
 * strict CSP regardless of what's configured here.
 *
 * Storage shape mirrors MarketingDefaults::scripts (`version` / `head` /
 * `body`). `enabled` is derived server-side from the two strings being
 * non-empty.
 */
export default function ScriptsEditor({ initial }: Props) {
    const [head, setHead] = useState(initial.head);
    const [body, setBody] = useState(initial.body);
    // Track the last-saved baseline locally: this tab persists via fetch (the
    // controller returns JSON, not an Inertia response), so page props aren't
    // refreshed on save — advance the baseline here so `dirty` clears.
    const [baseHead, setBaseHead] = useState(initial.head);
    const [baseBody, setBaseBody] = useState(initial.body);
    const [saving, setSaving] = useState(false);
    const [savedAt, setSavedAt] = useState<number | null>(null);
    const [error, setError] = useState<string | null>(null);

    const dirty = head !== baseHead || body !== baseBody;

    const save = async () => {
        if (saving) return;
        setSaving(true);
        setError(null);
        try {
            // fetch (not Inertia router) — the endpoint returns JSON; an
            // Inertia visit would render that raw JSON payload in the browser.
            const res = await fetch('/admin/marketing/scripts', {
                method: 'PATCH',
                credentials: 'same-origin',
                headers: csrfHeaders(),
                body: JSON.stringify({ head, body }),
            });
            if (!res.ok) {
                const err = await res.json().catch(() => null);
                setError(err?.message ?? `Save failed (${res.status}).`);
                return;
            }
            const data = (await res.json()) as { scripts?: ScriptsValue };
            // Reflect the server-normalized values (it trims + derives enabled).
            const savedHead = data.scripts?.head ?? head;
            const savedBody = data.scripts?.body ?? body;
            setHead(savedHead);
            setBody(savedBody);
            setBaseHead(savedHead);
            setBaseBody(savedBody);
            setSavedAt(Date.now());
        } catch {
            setError('Network error. Try again.');
        } finally {
            setSaving(false);
        }
    };

    return (
        <div className="space-y-6">
            <div>
                <h2 className="text-lg font-semibold text-foreground">Custom scripts</h2>
                <p className="mt-1 text-sm text-muted-foreground">
                    Paste vendor snippets (gtag, Facebook Pixel, Hotjar, Intercom, Plausible, etc.) to render on every public marketing page. Scripts here load on{' '}
                    <code className="rounded bg-muted px-1 py-0.5 text-xs">/</code>,{' '}
                    <code className="rounded bg-muted px-1 py-0.5 text-xs">/pricing</code>,{' '}
                    <code className="rounded bg-muted px-1 py-0.5 text-xs">/about</code>,{' '}
                    <code className="rounded bg-muted px-1 py-0.5 text-xs">/contact</code>,{' '}
                    <code className="rounded bg-muted px-1 py-0.5 text-xs">/templates</code>, legal pages, and admin-created custom pages. Admin, editor, and auth surfaces never include them.
                </p>
            </div>

            <div className="rounded-lg border border-warning/30 bg-warning/10 p-4 text-[13px]">
                <div className="flex gap-3">
                    <AlertTriangle className="mt-0.5 h-4 w-4 shrink-0 text-warning" />
                    <div className="space-y-1.5">
                        <p className="font-medium text-foreground">
                            Pasted code executes on every public page.
                        </p>
                        <p className="text-muted-foreground">
                            Only paste scripts from sources you trust. To make any vendor snippet work without errors, the public marketing pages switch to a permissive Content Security Policy whenever either slot is non-empty — admin and editor surfaces stay locked down regardless.
                        </p>
                    </div>
                </div>
            </div>

            <div className="space-y-2">
                <label
                    htmlFor="scripts-head"
                    className="block text-sm font-medium text-foreground"
                >
                    Head scripts
                </label>
                <p className="text-xs text-muted-foreground">
                    Injected inside <code>&lt;head&gt;</code> after Vite assets. Most analytics snippets (Google Tag Manager, gtag, Hotjar, Plausible) belong here.
                </p>
                <Textarea
                    id="scripts-head"
                    value={head}
                    onChange={(ev) => setHead(ev.target.value)}
                    rows={14}
                    spellCheck={false}
                    placeholder={'<!-- Google tag (gtag.js) -->\n<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXX"></script>\n<script>\n  window.dataLayer = window.dataLayer || [];\n  function gtag(){dataLayer.push(arguments);}\n  gtag(\'js\', new Date());\n  gtag(\'config\', \'G-XXXXXXXX\');\n</script>'}
                    className="font-mono text-[12px]"
                    data-testid="admin-marketing-scripts-head"
                />
                <p className="text-[11px] text-muted-foreground">{head.length.toLocaleString()} / 65,536 characters</p>
            </div>

            <div className="space-y-2">
                <label
                    htmlFor="scripts-body"
                    className="block text-sm font-medium text-foreground"
                >
                    Body scripts
                </label>
                <p className="text-xs text-muted-foreground">
                    Injected just before <code>&lt;/body&gt;</code>. Use for late-loaded widgets (Intercom messenger, Crisp chat, Drift) and any snippet the vendor specifies should run after the page renders.
                </p>
                <Textarea
                    id="scripts-body"
                    value={body}
                    onChange={(ev) => setBody(ev.target.value)}
                    rows={10}
                    spellCheck={false}
                    placeholder={'<!-- Intercom -->\n<script>\n  window.intercomSettings = { app_id: "xxxxx" };\n</script>\n<script>(function(){var w=window;var ic=w.Intercom;...})();</script>'}
                    className="font-mono text-[12px]"
                    data-testid="admin-marketing-scripts-body"
                />
                <p className="text-[11px] text-muted-foreground">{body.length.toLocaleString()} / 65,536 characters</p>
            </div>

            <div className="flex items-center gap-3 border-t border-border pt-4">
                <Button
                    type="button"
                    variant="primary"
                    onClick={save}
                    disabled={!dirty || saving}
                    data-testid="admin-marketing-scripts-save"
                >
                    {saving ? 'Saving…' : 'Save scripts'}
                </Button>
                {savedAt !== null && !dirty && (
                    <span className="inline-flex items-center gap-1.5 text-xs text-success">
                        <CheckCircle2 className="h-3.5 w-3.5" />
                        Saved
                    </span>
                )}
                {dirty && !error && (
                    <span className="text-xs text-muted-foreground">Unsaved changes</span>
                )}
                {error && (
                    <span className="inline-flex items-center gap-1.5 text-xs text-destructive">
                        <AlertTriangle className="h-3.5 w-3.5" />
                        {error}
                    </span>
                )}
            </div>
        </div>
    );
}
