import { Head, Link, router, useForm, usePage } from '@inertiajs/react';
import {
    ArrowUpRight,
    CalendarClock,
    Construction,
    Eye,
    Globe,
    Image as ImageIcon,
    Mail,
    Phone,
    Rocket,
    ShieldCheck,
    Sparkles,
} from 'lucide-react';
import { BrandingBackgroundGallery } from '@/components/crm/branding-background-gallery';
import { Callout, PageHeader, SectionCard } from '@/components/crm/page-header';
import { Field, FormActions } from '@/components/crm/form-field';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Spinner } from '@/components/ui/spinner';
import type { Branding, LaunchSettingsProps } from '@/types';

const textareaClassName =
    'border-input dark:bg-input/30 min-h-28 w-full rounded-md border bg-transparent px-3 py-2 text-sm leading-relaxed shadow-xs outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]';

/**
 * Settings -> Coming soon.
 *
 * One switch, and the words that go on the page while the site is not public
 * yet. Two halves on purpose: the form on the left, and the page itself on the
 * right, so a sentence can be judged by how it reads rather than by how it
 * fills a textarea.
 *
 * The miniature beside the form is not the real page — that is what the
 * preview button opens — but it is built from the boxes as they are being
 * typed, which is what makes writing the words quick.
 */
export default function ComingSoonSettings({
    launch,
    fields,
    defaults,
    previewUrl,
    background_images,
    background_path,
}: LaunchSettingsProps) {
    const { branding } = usePage<{ branding: Branding }>().props;

    const form = useForm({
        enabled: launch.enabled,
        eyebrow: fields.eyebrow ?? '',
        headline: fields.headline ?? '',
        message: fields.message ?? '',
        expected_on: fields.expected_on ?? '',
        contact_email: fields.contact_email ?? '',
        contact_phone: fields.contact_phone ?? '',
    });

    const submit = () => {
        form.put('/settings/coming-soon', { preserveScroll: true });
    };

    const useBackground = (path: string | null) => {
        router.post(
            '/settings/coming-soon/background',
            { path },
            // A photograph is one decision, so it applies at once. Keeping the
            // component state means words typed but not yet saved stay put.
            { preserveScroll: true, preserveState: true },
        );
    };

    const enabled = form.data.enabled;
    const previewEyebrow = form.data.eyebrow.trim() || defaults.eyebrow;
    const previewHeadline = form.data.headline.trim() || defaults.headline;
    const previewMessage = form.data.message.trim() || defaults.message;
    const previewDate = monthLabel(form.data.expected_on);
    const previewEmail = form.data.contact_email.trim() || launch.contact_email;
    const previewPhone = form.data.contact_phone.trim() || launch.contact_phone;
    // Compared against what was stored rather than against a snapshot of the
    // form, so typing a word and deleting it again leaves Save where it was.
    const dirty =
        form.data.enabled !== launch.enabled ||
        form.data.eyebrow !== (fields.eyebrow ?? '') ||
        form.data.headline !== (fields.headline ?? '') ||
        form.data.message !== (fields.message ?? '') ||
        form.data.expected_on !== (fields.expected_on ?? '') ||
        form.data.contact_email !== (fields.contact_email ?? '') ||
        form.data.contact_phone !== (fields.contact_phone ?? '');

    return (
        <>
            <Head title="Coming soon" />

            <PageHeader
                title="Coming soon"
                description="A holding page for the site while it is still being finished. Visitors see it instead of the portal; your team keeps signing in."
                eyebrow={
                    <>
                        <Construction className="size-3.5" />
                        <span>Company</span>
                    </>
                }
                actions={
                    <Button asChild variant="outline" size="sm">
                        <a
                            href={previewUrl}
                            target="_blank"
                            rel="noreferrer"
                        >
                            <Eye />
                            Open the page
                            <ArrowUpRight className="size-3.5 opacity-60" />
                        </a>
                    </Button>
                }
            />

            <Callout
                tone={enabled ? 'warning' : 'info'}
                icon={enabled ? Rocket : Globe}
                title={
                    enabled
                        ? 'Visitors are seeing the holding page'
                        : 'The site is public'
                }
            >
                {enabled
                    ? 'Anyone who is not signed in lands on this page, at whatever address they asked for. Staff still sign in at /login and use the CRM as normal, a customer who is already signed in keeps their portal, and the shared status board still opens with a link the office issued.'
                    : 'Every page is reachable as usual. Turning this on puts the holding page in front of visitors and leaves your team and your signed-in customers exactly where they are.'}
            </Callout>

            <div className="grid items-start gap-5 xl:grid-cols-[minmax(0,1fr)_22rem]">
                <form
                    className="flex flex-col gap-5"
                    onSubmit={(event) => {
                        event.preventDefault();
                        submit();
                    }}
                >
                    <SectionCard
                        title="The switch"
                        description="Where the line between the public and your team is drawn."
                        icon={ShieldCheck}
                        tone={enabled ? 'warning' : 'slate'}
                    >
                        <div className="flex items-start gap-3 rounded-lg bg-muted/40 p-3 ring-1 ring-inset ring-hairline">
                            <Checkbox
                                id="enabled"
                                className="mt-0.5"
                                checked={form.data.enabled}
                                onCheckedChange={(checked) =>
                                    form.setData('enabled', checked === true)
                                }
                            />
                            <div className="min-w-0">
                                <Label htmlFor="enabled">
                                    Show the holding page to visitors
                                </Label>
                                <p className="mt-1 text-xs leading-relaxed text-muted-foreground">
                                    A visitor is anybody who is not signed in.
                                    Staff accounts, and customers with a portal
                                    session, are unaffected — there is always a
                                    way in.
                                </p>
                                <InputErrorish message={form.errors.enabled} />
                            </div>
                        </div>

                        <ul className="mt-4 grid gap-2 text-xs leading-relaxed text-muted-foreground sm:grid-cols-2">
                            {[
                                'The front page, and every other public address, shows one page.',
                                'Staff sign-in, password resets and passkeys keep working.',
                                'The shared status board still opens with an issued link.',
                                'The page carries your logo, colours and contact details.',
                                'Search engines are told not to index it.',
                            ].map((line) => (
                                <li key={line} className="flex gap-2">
                                    <Sparkles className="mt-0.5 size-3.5 shrink-0 text-solar" />
                                    <span>{line}</span>
                                </li>
                            ))}
                        </ul>
                    </SectionCard>

                    <SectionCard
                        title="The words on the page"
                        description="Every box falls back to a written default when it is left empty, so the page is never blank."
                        icon={Construction}
                        tone="solar"
                    >
                        <div className="grid gap-4 sm:grid-cols-2">
                            <Field
                                label="Eyebrow"
                                htmlFor="eyebrow"
                                hint="A small label above the headline"
                                error={form.errors.eyebrow}
                            >
                                <Input
                                    id="eyebrow"
                                    value={form.data.eyebrow}
                                    placeholder={defaults.eyebrow}
                                    maxLength={60}
                                    onChange={(event) =>
                                        form.setData(
                                            'eyebrow',
                                            event.target.value,
                                        )
                                    }
                                />
                            </Field>

                            <Field
                                label="Expected launch"
                                htmlFor="expected_on"
                                hint="Shown as a month"
                                error={form.errors.expected_on}
                            >
                                <Input
                                    id="expected_on"
                                    type="date"
                                    value={form.data.expected_on}
                                    onChange={(event) =>
                                        form.setData(
                                            'expected_on',
                                            event.target.value,
                                        )
                                    }
                                />
                            </Field>

                            <Field
                                label="Headline"
                                htmlFor="headline"
                                error={form.errors.headline}
                                className="sm:col-span-2"
                            >
                                <Input
                                    id="headline"
                                    value={form.data.headline}
                                    placeholder={defaults.headline}
                                    maxLength={120}
                                    onChange={(event) =>
                                        form.setData(
                                            'headline',
                                            event.target.value,
                                        )
                                    }
                                />
                            </Field>

                            <Field
                                label="Message"
                                htmlFor="message"
                                hint={`${form.data.message.length}/700`}
                                error={form.errors.message}
                                className="sm:col-span-2"
                            >
                                <textarea
                                    id="message"
                                    className={textareaClassName}
                                    value={form.data.message}
                                    placeholder={defaults.message}
                                    maxLength={700}
                                    onChange={(event) =>
                                        form.setData(
                                            'message',
                                            event.target.value,
                                        )
                                    }
                                />
                            </Field>
                        </div>
                    </SectionCard>

                    <SectionCard
                        title="Page background"
                        description="The photograph behind the holding page. Choose one already uploaded in Company profile, or leave it on the plain ground."
                        icon={ImageIcon}
                        tone="info"
                    >
                        <BrandingBackgroundGallery
                            title="Uploaded backgrounds"
                            description="The same library the sign-in screen uses. Choosing one here changes only the holding page."
                            images={background_images}
                            selectedPath={background_path}
                            onSelect={useBackground}
                            onClear={() => useBackground(null)}
                            emptyMessage="No backgrounds saved yet. Upload one in Company profile, then choose it here."
                            divided={false}
                        />
                    </SectionCard>

                    <SectionCard
                        title="Who to contact"
                        description="Shown beside the message so a customer with a fault knows the office has not disappeared."
                        icon={Phone}
                        tone="teal"
                    >
                        <div className="grid gap-4 sm:grid-cols-2">
                            <Field
                                label="Email"
                                htmlFor="contact_email"
                                hint="Defaults to the company email"
                                error={form.errors.contact_email}
                            >
                                <Input
                                    id="contact_email"
                                    type="email"
                                    value={form.data.contact_email}
                                    placeholder={
                                        launch.contact_email ?? 'office@example.com'
                                    }
                                    onChange={(event) =>
                                        form.setData(
                                            'contact_email',
                                            event.target.value,
                                        )
                                    }
                                />
                            </Field>

                            <Field
                                label="Phone"
                                htmlFor="contact_phone"
                                hint="Defaults to the company number"
                                error={form.errors.contact_phone}
                            >
                                <Input
                                    id="contact_phone"
                                    value={form.data.contact_phone}
                                    placeholder={
                                        launch.contact_phone ?? '07 0000 0000'
                                    }
                                    onChange={(event) =>
                                        form.setData(
                                            'contact_phone',
                                            event.target.value,
                                        )
                                    }
                                />
                            </Field>
                        </div>

                        <FormActions
                            note={
                                dirty
                                    ? 'Unsaved changes.'
                                    : 'Everything here is saved already.'
                            }
                        >
                            <Link
                                href={previewUrl}
                                target="_blank"
                                rel="noreferrer"
                                className="text-xs text-muted-foreground underline underline-offset-4 hover:text-foreground"
                            >
                                See the real page
                            </Link>
                            <Button
                                type="submit"
                                disabled={form.processing || !dirty}
                            >
                                {form.processing && <Spinner />}
                                Save
                            </Button>
                        </FormActions>
                    </SectionCard>
                </form>

                <aside className="xl:sticky xl:top-6">
                    <div className="overflow-hidden rounded-xl ring-1 ring-hairline">
                        <div className="relative overflow-hidden bg-[#0a1421] px-5 py-6 text-white">
                            {launch.background_url ? (
                                <>
                                    <div
                                        aria-hidden
                                        className="absolute inset-0 bg-cover bg-center"
                                        style={{
                                            backgroundImage: `url(${launch.background_url})`,
                                        }}
                                    />
                                    <div
                                        aria-hidden
                                        className="absolute inset-0 bg-[#0a1421]/70"
                                    />
                                </>
                            ) : null}
                            <div
                                aria-hidden
                                className="pointer-events-none absolute -top-24 -right-16 size-56 rounded-full opacity-25 blur-2xl"
                                style={{
                                    backgroundColor:
                                        branding?.primary_color ?? '#f0a020',
                                }}
                            />
                            <div className="relative">
                                <div className="flex items-center justify-between gap-3">
                                    <span className="truncate text-[11px] font-semibold tracking-tight">
                                        {branding?.name ?? 'Your company'}
                                    </span>
                                    <span className="text-[9px] tracking-[0.12em] text-white/35 uppercase">
                                        Team sign in
                                    </span>
                                </div>

                                <p className="mt-7 inline-flex items-center gap-1.5 rounded-full border border-white/15 bg-white/[0.07] px-2.5 py-0.5 text-[9px] font-medium tracking-[0.12em] text-white/70 uppercase">
                                    <span className="size-1 rounded-full bg-white/80" />
                                    {previewEyebrow}
                                </p>

                                <p className="mt-3 text-lg leading-snug font-semibold tracking-tight text-balance">
                                    {previewHeadline}
                                </p>

                                <p className="mt-2.5 line-clamp-5 text-[11px] leading-relaxed text-white/55">
                                    {previewMessage}
                                </p>

                                <div className="mt-4 flex flex-wrap gap-1.5 text-[10px] text-white/70">
                                    {previewDate ? (
                                        <span className="inline-flex items-center gap-1 rounded-full border border-white/15 bg-white/[0.06] px-2 py-1">
                                            <CalendarClock className="size-3" />
                                            {previewDate}
                                        </span>
                                    ) : null}
                                    {previewPhone ? (
                                        <span className="inline-flex items-center gap-1 rounded-full border border-white/15 bg-white/[0.06] px-2 py-1">
                                            <Phone className="size-3" />
                                            {previewPhone}
                                        </span>
                                    ) : null}
                                    {previewEmail ? (
                                        <span className="inline-flex max-w-full items-center gap-1 truncate rounded-full border border-white/15 bg-white/[0.06] px-2 py-1">
                                            <Mail className="size-3" />
                                            <span className="truncate">
                                                {previewEmail}
                                            </span>
                                        </span>
                                    ) : null}
                                </div>
                            </div>
                        </div>

                        <div className="flex items-start gap-2 border-t border-hairline bg-card px-4 py-3 text-[11px] leading-relaxed text-muted-foreground">
                            <Eye className="mt-0.5 size-3.5 shrink-0" />
                            <span>
                                A miniature of the real page, built from what you
                                have typed. The page itself opens from{' '}
                                <span className="whitespace-nowrap">
                                    “Open the page”.
                                </span>
                            </span>
                        </div>
                    </div>

                    <p className="mt-3 px-1 text-[11px] leading-relaxed text-muted-foreground">
                        {enabled
                            ? 'While this is on, nobody new can reach the portal or an inspection link. That is the point of a holding page — switch it off on launch day. The shared status board is the one exception: a link the office issued still opens it, because its holder has no account to sign in with.'
                            : 'Leave the switch off until the site is ready to be seen. Turning it on needs no deploy, and turning it off restores everything exactly as it was.'}
                    </p>
                </aside>
            </div>
        </>
    );
}

/**
 * "March 2027" from a date input's value. The page does this server-side for
 * the real render; here it is only for the miniature.
 */
function monthLabel(value: string): string | null {
    if (!value) {
        return null;
    }

    const date = new Date(`${value}T00:00:00`);

    if (Number.isNaN(date.getTime())) {
        return null;
    }

    return date.toLocaleDateString('en-AU', {
        month: 'long',
        year: 'numeric',
    });
}

/**
 * The boolean field's error, which the shared Field component cannot show
 * because the checkbox lives beside its own label.
 */
function InputErrorish({ message }: { message?: string }) {
    if (!message) {
        return null;
    }

    return (
        <p className="mt-1 text-xs font-medium text-danger" role="alert">
            {message}
        </p>
    );
}
