import { useEffect, useMemo, useState } from 'react';
import { Head, Link, useForm } from '@inertiajs/react';
import {
    Check,
    CheckCircle2,
    ClipboardCheck,
    Copy,
    FileSignature,
    Info,
    Link2,
    Send,
    ShieldCheck,
    Smartphone,
} from 'lucide-react';
import { Combobox, type ComboboxOption } from '@/components/crm/combobox';
import { Callout, PageHeader, SectionCard } from '@/components/crm/page-header';
import { FormField } from '@/components/crm/native-select';
import { Button } from '@/components/ui/button';
import { copyToClipboard } from '@/lib/clipboard';
import { cn } from '@/lib/utils';
import { index as inspectionsIndex } from '@/routes/inspections';
import type {
    InspectionFormProps,
    TicketCustomerOption,
    TicketJobOption,
} from '@/types';

/**
 * Open a report against a job.
 *
 * The customer and job pickers are the ticket form's own, because this is the
 * same question: which install is this about? Naming the customer narrows the
 * jobs to their own work, and choosing the job offers the crew who did it.
 */
export default function CreateInspection({
    purposes,
    installers,
    preselectedJob,
    preselectedCustomer,
    sections,
    intake,
}: InspectionFormProps) {
    const { data, setData, post, processing, errors } = useForm<{
        job_id: number | null;
        purpose: string;
        installer_id: number | null;
        send: boolean;
    }>({
        job_id: preselectedJob?.value ?? null,
        purpose: purposes[0]?.value ?? 'commissioning',
        installer_id: preselectedJob?.installer_id ?? null,
        send: true,
    });

    const [customerId, setCustomerId] = useState<number | null>(
        preselectedJob?.customer_id ?? null,
    );
    const [customerOptions, setCustomerOptions] = useState<
        TicketCustomerOption[]
    >(preselectedCustomer ? [preselectedCustomer] : []);
    const [jobOptions, setJobOptions] = useState<TicketJobOption[]>(
        preselectedJob ? [preselectedJob] : [],
    );
    const [loadingJobs, setLoadingJobs] = useState(false);
    const [copiedIntake, setCopiedIntake] = useState(false);

    const selectedJob =
        jobOptions.find((job) => job.value === data.job_id) ??
        (preselectedJob?.value === data.job_id ? preselectedJob : null);

    const selectedCustomer =
        customerOptions.find((customer) => customer.value === customerId) ??
        null;

    // The customer's own work, searched on the server. There are thousands of
    // customers and more jobs than that, so nothing here is shipped with the
    // page.
    useEffect(() => {
        if (customerId === null) {
            setJobOptions(preselectedJob ? [preselectedJob] : []);
            setLoadingJobs(false);

            return;
        }

        const controller = new AbortController();
        setLoadingJobs(true);

        fetch(`/lookups/jobs?customer=${customerId}`, {
            headers: { Accept: 'application/json' },
            signal: controller.signal,
        })
            .then((response) =>
                response.ok
                    ? (response.json() as Promise<{
                          options?: TicketJobOption[];
                      }>)
                    : { options: [] },
            )
            .then((payload) => {
                if (controller.signal.aborted) {
                    return;
                }

                setJobOptions(payload.options ?? []);
            })
            .catch(() => {
                // Changing customer twice in a row cancels the first request.
            })
            .finally(() => {
                if (!controller.signal.aborted) {
                    setLoadingJobs(false);
                }
            });

        return () => controller.abort();
    }, [customerId, preselectedJob]);

    const jobs = useMemo(
        () =>
            jobOptions.map((job) => ({
                value: job.value,
                label: job.label,
                note: job.installer
                    ? `Installed by ${job.installer}`
                    : job.installer_company
                      ? `Installed by ${job.installer_company} — not in the register`
                      : 'No installer on this job yet',
                meta: job.status,
            })),
        [jobOptions],
    );

    const chooseCustomer = (
        nextId: number | null,
        option: ComboboxOption | null,
    ) => {
        const chosen = option as TicketCustomerOption | null;

        if (chosen !== null) {
            setCustomerOptions((previous) =>
                previous.some((customer) => customer.value === chosen.value)
                    ? previous
                    : [chosen, ...previous],
            );
        }

        setCustomerId(nextId);

        // A job that belongs to somebody else can no longer be the one.
        if (selectedJob && selectedJob.customer_id !== nextId) {
            setData('job_id', null);
            setData('installer_id', null);
        }
    };

    const chooseJob = (nextId: number | null, option: ComboboxOption | null) => {
        const job = option as TicketJobOption | null;

        setData('job_id', nextId);
        setData('installer_id', job?.installer_id ?? null);
    };

    const submit = (event: React.FormEvent) => {
        event.preventDefault();
        post('/inspections');
    };

    const copyIntakeLink = async () => {
        if (!intake.url) {
            return;
        }

        // Copying works over plain HTTP too — see the helper.
        const copied = await copyToClipboard(intake.url);

        setCopiedIntake(copied);

        if (copied) {
            window.setTimeout(() => setCopiedIntake(false), 2200);
        }
    };

    return (
        <>
            <Head title="Request an inspection" />

            <div className="flex flex-col gap-5">
                <PageHeader
                    eyebrow={
                        <>
                            <ClipboardCheck className="text-solar size-3.5" />
                            <span>New inspection report</span>
                        </>
                    }
                    title="Request an inspection"
                    description="Opens a standard Australian inspection and warranty report against a job and gives you a link to send the crew. They fill it in on a phone — photos, test results and a signature — with no account to create."
                    actions={
                        <Button variant="outline" size="sm" asChild>
                            <Link href={inspectionsIndex()}>Cancel</Link>
                        </Button>
                    }
                />

                {intake.can_manage ? (
                    <div className="flex flex-wrap items-center gap-x-3 gap-y-2 rounded-xl bg-violet-500/5 px-4 py-3 ring-1 ring-violet-500/20">
                        <Smartphone className="size-4 shrink-0 text-violet-700 dark:text-violet-400" />
                        <p className="min-w-0 flex-1 text-xs leading-relaxed">
                            <span className="font-medium text-foreground">
                                Is a crew already on site?
                            </span>{' '}
                            {intake.open && intake.url
                                ? 'They can start this same report themselves from the standing on-site link — they confirm the client and the address, and no job number is needed.'
                                : 'The standing on-site link is closed, so a crew cannot start a report at the property. Open one from All reports.'}
                        </p>
                        {intake.open && intake.url ? (
                            <Button
                                type="button"
                                size="sm"
                                variant="outline"
                                onClick={copyIntakeLink}
                            >
                                {copiedIntake ? <Check /> : <Copy />}
                                {copiedIntake
                                    ? 'Copied'
                                    : 'Copy on-site link'}
                            </Button>
                        ) : (
                            <Button size="sm" variant="outline" asChild>
                                <Link href={inspectionsIndex()}>
                                    All reports
                                </Link>
                            </Button>
                        )}
                    </div>
                ) : null}

                <form onSubmit={submit} className="grid gap-5 lg:grid-cols-3">
                    <div className="flex flex-col gap-5 lg:col-span-2">
                        <SectionCard
                            title="The job"
                            description="Which install this is about. The job's own details prefill the crew's form."
                            icon={ClipboardCheck}
                            tone="solar"
                        >
                            <div className="grid gap-x-6 gap-y-4 sm:grid-cols-2">
                                <FormField
                                    label="Customer"
                                    htmlFor="customer_picker"
                                    hint="Name, phone, customer number or address"
                                >
                                    <Combobox
                                        id="customer_picker"
                                        name="customer_picker"
                                        value={customerId}
                                        onChange={chooseCustomer}
                                        options={customerOptions.map(
                                            (customer) => ({
                                                value: customer.value,
                                                label: customer.label,
                                                note: customer.note,
                                            }),
                                        )}
                                        remote={{ url: '/lookups/customers' }}
                                        placeholder="Search customers"
                                        clearLabel="Choose again"
                                        emptyLabel="No customer matches that"
                                    />
                                </FormField>

                                <FormField
                                    label="Job"
                                    htmlFor="job_id"
                                    error={errors.job_id}
                                    hint={
                                        customerId === null
                                            ? 'Choose the customer first — a job is always theirs'
                                            : loadingJobs
                                              ? 'Loading their jobs…'
                                              : 'Their own work, newest first'
                                    }
                                >
                                    <Combobox
                                        id="job_id"
                                        name="job_id"
                                        value={data.job_id}
                                        onChange={chooseJob}
                                        options={jobs}
                                        disabled={customerId === null}
                                        placeholder={
                                            customerId === null
                                                ? 'Choose the customer first'
                                                : 'Search their jobs'
                                        }
                                        clearLabel="No job chosen"
                                        emptyLabel={
                                            loadingJobs
                                                ? 'Loading their jobs…'
                                                : 'No jobs on this customer'
                                        }
                                    />
                                </FormField>
                            </div>

                            {selectedJob ? (
                                <div className="mt-4 grid gap-2 rounded-lg bg-muted/50 px-4 py-3 text-xs sm:grid-cols-2">
                                    <span>
                                        <span className="text-muted-foreground">
                                            Customer:{' '}
                                        </span>
                                        {selectedCustomer?.label ??
                                            selectedJob.customer ??
                                            '—'}
                                    </span>
                                    <span>
                                        <span className="text-muted-foreground">
                                            Job status:{' '}
                                        </span>
                                        {selectedJob.status}
                                    </span>
                                    <span>
                                        <span className="text-muted-foreground">
                                            Crew on the job:{' '}
                                        </span>
                                        {selectedJob.installer ??
                                            selectedJob.installer_company ??
                                            'Nobody recorded'}
                                    </span>
                                </div>
                            ) : null}
                        </SectionCard>

                        <SectionCard
                            title="Why the crew is going"
                            description="This is printed on the report and in the email that carries the link."
                            icon={FileSignature}
                        >
                            <div className="grid gap-2 sm:grid-cols-2">
                                {purposes.map((option) => {
                                    const selected = data.purpose === option.value;

                                    return (
                                        <button
                                            key={option.value}
                                            type="button"
                                            onClick={() =>
                                                setData('purpose', option.value)
                                            }
                                            className={cn(
                                                'flex items-start gap-3 rounded-lg px-4 py-3 text-left ring-1 transition-colors',
                                                selected
                                                    ? 'bg-solar-soft/60 ring-solar/40'
                                                    : 'ring-hairline hover:bg-muted/60',
                                            )}
                                        >
                                            <span
                                                className={cn(
                                                    'mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-full ring-1',
                                                    selected
                                                        ? 'bg-solar text-solar-ink ring-solar'
                                                        : 'ring-hairline',
                                                )}
                                            >
                                                {selected ? (
                                                    <CheckCircle2 className="size-3" />
                                                ) : null}
                                            </span>
                                            <span className="min-w-0">
                                                <span className="block text-sm font-medium">
                                                    {option.label}
                                                </span>
                                                <span className="text-muted-foreground mt-0.5 block text-xs leading-relaxed">
                                                    {option.description}
                                                </span>
                                            </span>
                                        </button>
                                    );
                                })}
                            </div>
                        </SectionCard>

                        <SectionCard
                            title="Who is being asked"
                            description="The crew who did the work is filled in from the job. Anybody on the register can be asked instead."
                            icon={Send}
                            tone="violet"
                        >
                            <div className="grid gap-x-6 gap-y-4 sm:grid-cols-2">
                                <FormField
                                    label="Installer"
                                    htmlFor="installer_id"
                                    error={errors.installer_id}
                                    hint={
                                        selectedJob?.installer
                                            ? `From the job — ${selectedJob.installer}`
                                            : 'Nobody is assigned, so the link is yours to copy and send'
                                    }
                                >
                                    <Combobox
                                        id="installer_id"
                                        name="installer_id"
                                        value={data.installer_id}
                                        onChange={(value) => setData('installer_id', value)}
                                        options={installers.map((installer) => ({
                                            value: installer.value,
                                            label: installer.label,
                                            note: installer.note,
                                        }))}
                                        placeholder="Search the register"
                                        clearLabel="Nobody in particular"
                                    />
                                </FormField>

                                <div className="flex flex-col justify-end">
                                    <label
                                        htmlFor="send"
                                        className="flex cursor-pointer items-start gap-3 rounded-lg px-3 py-2.5 ring-1 ring-hairline"
                                    >
                                        <input
                                            id="send"
                                            type="checkbox"
                                            checked={data.send}
                                            onChange={(event) =>
                                                setData('send', event.target.checked)
                                            }
                                            className="accent-solar mt-0.5 size-4"
                                        />
                                        <span>
                                            <span className="block text-sm font-medium">
                                                Email the link now
                                            </span>
                                            <span className="text-muted-foreground block text-xs leading-relaxed">
                                                Sent to the address on the
                                                installer's record. Left unticked,
                                                the report opens with a link for
                                                you to copy.
                                            </span>
                                        </span>
                                    </label>
                                </div>
                            </div>
                        </SectionCard>

                        <div className="flex flex-wrap items-center justify-between gap-3">
                            <p className="text-muted-foreground flex items-center gap-1.5 text-xs">
                                <Link2 className="size-3.5" />
                                The link lasts 30 days and needs no account.
                            </p>
                            <Button
                                type="submit"
                                disabled={processing || data.job_id === null}
                            >
                                <Send />
                                {processing ? 'Opening…' : 'Open the report'}
                            </Button>
                        </div>
                    </div>

                    <div className="flex flex-col gap-5">
                        <Callout
                            tone="info"
                            icon={Info}
                            title="What the crew will be asked"
                        >
                            The checklist follows the standards an Australian
                            installation is inspected against, so the same
                            report works for a handover, a warranty claim and an
                            audit.
                        </Callout>

                        <SectionCard
                            title={`${sections.reduce((total, section) => total + section.items, 0)} checks, six sections`}
                            description="Written on site, on a phone, with photos and a signature."
                            icon={ShieldCheck}
                            tone="emerald"
                            flush
                        >
                            <ul className="divide-y divide-hairline">
                                {sections.map((section) => (
                                    <li
                                        key={section.key}
                                        className="flex items-start justify-between gap-3 px-5 py-3"
                                    >
                                        <div className="min-w-0">
                                            <p className="text-sm font-medium">
                                                {section.title}
                                            </p>
                                            <p className="text-muted-foreground mt-0.5 text-xs">
                                                {section.standard}
                                                {section.battery_only
                                                    ? ' · battery systems only'
                                                    : ''}
                                            </p>
                                        </div>
                                        <span className="crm-num text-muted-foreground shrink-0 text-xs">
                                            {section.items}
                                        </span>
                                    </li>
                                ))}
                            </ul>
                        </SectionCard>

                        <SectionCard
                            title="What the crew needs with them"
                            description="The form asks for these, so the email lists them too."
                            icon={FileSignature}
                        >
                            <ul className="text-muted-foreground space-y-1.5 text-xs leading-relaxed">
                                <li>Their test instrument and its calibration date.</li>
                                <li>Their electrical licence number.</li>
                                <li>
                                    At least three photos: array, inverter and
                                    switchboard.
                                </li>
                                <li>
                                    A PDF or Word copy of their own test sheet,
                                    if they keep one.
                                </li>
                            </ul>
                        </SectionCard>
                    </div>
                </form>
            </div>
        </>
    );
}
