import { useState } from "react";
import { Form, Head, Link, router, useForm } from "@inertiajs/react";
import {
    BriefcaseBusiness,
    Building2,
    FileText,
    HardHat,
    LifeBuoy,
    Link2,
    MapPin,
    MapPinned,
    Pencil,
    Plus,
    Target,
    Trash2,
    Unlink,
    UserRound,
    Wallet,
} from "lucide-react";
import SiteController from "@/actions/App/Http/Controllers/SiteController";
import { Combobox } from "@/components/crm/combobox";
import { OwnershipHistory } from "@/components/crm/ownership-history";
import { TransferOwnershipDialog } from "@/components/crm/transfer-ownership-dialog";
import {
    Callout,
    DetailRow,
    EmptyState,
    MetaStrip,
    PageHeader,
    SectionCard,
} from "@/components/crm/page-header";
import { RichText } from "@/components/crm/rich-text";
import { SectionNav } from "@/components/crm/section-nav";
import { useRelease } from "@/hooks/use-release";
import {
    FormField,
    NativeSelect,
    StaticField,
} from "@/components/crm/native-select";
import {
    JobStatusBadge,
    RuleFlag,
    StatusDot,
    StatusLabel,
    StatusPill,
} from "@/components/crm/status-badge";
import { Button } from "@/components/ui/button";
import {
    Dialog,
    DialogClose,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
    DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import {
    Table,
    TableBody,
    TableCell,
    TableHead,
    TableHeader,
    TableRow,
} from "@/components/ui/table";
import {
    formatAddress,
    formatCurrency,
    formatDate,
    formatDuration,
    formatNumber,
    formatRelative,
} from "@/lib/format";
import { cn } from "@/lib/utils";
import {
    create as customerCreate,
    destroy as customerDestroy,
    index as customersIndex,
    profile as customerProfile,
    show as customerShow,
} from "@/routes/customers";
import { detach as detachBuilder } from "@/routes/customers/builder";
import { attach as attachClient } from "@/routes/customers/clients";
import { create as jobCreate, show as jobShow } from "@/routes/jobs";
import { customers as customersLookup } from "@/routes/lookups";
import { create as ticketsCreate, show as ticketShow } from "@/routes/tickets";
import type {
    CustomerDetail,
    CustomerSummary,
    DocumentSummary,
    JobSummary,
    OptionsBundle,
    SiteSummary,
    TicketCounts,
    TicketSummary,
} from "@/types";

type PageProps = {
    customer: CustomerDetail;
    /** Empty unless this record is a builder account. */
    clients: CustomerSummary[];
    jobs: JobSummary[];
    financials: {
        contract_value: number;
        deposit: number;
        invoiced: number;
        paid: number;
        outstanding: number;
        invoice_count: number;
    } | null;
    documents: DocumentSummary[];
    tickets: TicketSummary[];
    ticketCounts: TicketCounts;
    options: OptionsBundle;
    can: {
        update: boolean;
        delete: boolean;
        createJob: boolean;
        createSite: boolean;
        uploadDocuments: boolean;
        createTicket: boolean;
        transferOwnership: boolean;
        /** May add a client to this builder. */
        createClient: boolean;
        /** May put a client under this builder, or take one off it. */
        linkBuilder: boolean;
    };
};

export default function CustomerShow({
    customer,
    clients,
    jobs,
    financials,
    documents,
    tickets,
    ticketCounts,
    options,
    can,
}: PageProps) {
    const [siteDialogOpen, setSiteDialogOpen] = useState(false);
    const [assignOpen, setAssignOpen] = useState(false);
    // Jobs and tickets are released parts of their own. A customer page does
    // not carry a panel for a part the rest of the system is not showing.
    const { enabled } = useRelease();

    // The whole register is searched on request, so the picker starts empty and
    // asks the lookup endpoint as the person types.
    const assign = useForm<{ customer_id: number | null }>({
        customer_id: null,
    });

    const isBuilder = customer.type.value === "builder";

    const billingAddress = formatAddress([
        customer.billing.line1,
        customer.billing.line2,
        customer.billing.suburb,
        customer.billing.state_label,
        customer.billing.postcode,
    ]);

    const handleDelete = () => {
        const confirmed = window.confirm(
            `Archive ${customer.name}? Their jobs and sites stay on file, but the customer will no longer appear in lists.`,
        );

        if (confirmed) {
            router.delete(customerDestroy(customer.id));
        }
    };

    return (
        <>
            <Head title={customer.name} />

            <div className="flex flex-col gap-5">
                <PageHeader
                    eyebrow={
                        <>
                            <Building2 className="text-solar size-3.5" />
                            <span>{customer.customer_number}</span>
                            <span
                                aria-hidden
                                className="text-muted-foreground/50"
                            >
                                ·
                            </span>
                            <span>{customer.type.label}</span>
                            {customer.abn ? (
                                <>
                                    <span
                                        aria-hidden
                                        className="text-muted-foreground/50"
                                    >
                                        ·
                                    </span>
                                    <span>ABN {customer.abn}</span>
                                </>
                            ) : null}
                        </>
                    }
                    title={customer.name}
                    description={
                        billingAddress
                            ? `Billing address: ${billingAddress}`
                            : "No billing address recorded yet."
                    }
                    actions={
                        <>
                            {can.createJob ? (
                                <Button variant="outline" asChild>
                                    <Link
                                        href={jobCreate({
                                            query: { customer: customer.id },
                                        })}
                                    >
                                        <Plus />
                                        New job
                                    </Link>
                                </Button>
                            ) : null}
                            <Button variant="outline" asChild>
                                <Link href={customerProfile(customer.id)}>
                                    <Pencil />
                                    Profile
                                </Link>
                            </Button>
                            {can.delete ? (
                                <Button
                                    variant="destructive"
                                    onClick={handleDelete}
                                    data-test="archive-customer-button"
                                >
                                    <Trash2 />
                                    Archive
                                </Button>
                            ) : null}
                        </>
                    }
                />

                <MetaStrip
                    items={[
                        {
                            label: "Sites",
                            value: formatNumber(customer.sites.length),
                        },
                        // The job counts belong to the Jobs part; a customer
                        // page shown before that part is released does not
                        // carry a count of work it cannot open.
                        ...(enabled("jobs")
                            ? [
                                  {
                                      label: "Jobs",
                                      value: formatNumber(
                                          customer.jobs_count,
                                      ),
                                  },
                                  {
                                      label: "Active jobs",
                                      value: formatNumber(
                                          customer.active_jobs_count,
                                      ),
                                      tone:
                                          (customer.active_jobs_count ?? 0) > 0
                                              ? "solar"
                                              : undefined,
                                  },
                              ]
                            : []),
                        {
                            label: "Customer since",
                            value: formatDate(customer.created_at),
                        },
                        {
                            label: "Last contacted",
                            value: formatRelative(customer.last_contacted_at),
                        },
                        ...(isBuilder
                            ? [
                                  {
                                      label: "Clients",
                                      value: formatNumber(clients.length),
                                      tone: "solar",
                                  },
                              ]
                            : []),
                    ]}
                />

                {/* Whose client this is. The note stays on the record rather
                    than in a field somebody has to look for, because a
                    household's work, warranty and billing all come through
                    the builder named here. */}
                {customer.builder ? (
                    <Callout
                        tone="info"
                        icon={HardHat}
                        title={`Under ${customer.builder.name}`}
                        actions={
                            can.linkBuilder ? (
                                <Button
                                    variant="outline"
                                    size="sm"
                                    onClick={() => {
                                        if (
                                            window.confirm(
                                                `Take ${customer.name} off ${customer.builder?.name}? Their sites, jobs and billing stay where they are.`,
                                            )
                                        ) {
                                            router.delete(
                                                detachBuilder.url(customer.id),
                                                { preserveScroll: true },
                                            );
                                        }
                                    }}
                                    data-test="detach-builder-button"
                                >
                                    <Unlink />
                                    Take off builder
                                </Button>
                            ) : null
                        }
                    >
                        This client was introduced by{" "}
                        <Link
                            href={customerShow(customer.builder.id)}
                            className="font-medium underline"
                        >
                            {customer.builder.name}
                        </Link>{" "}
                        ({customer.builder.customer_number}). New work for them
                        is raised against this record, and it follows into the
                        builder's client list.
                    </Callout>
                ) : null}

                <SectionNav
                    sections={[
                        { id: "overview", label: "Contact" },
                        { id: "billing", label: "Billing" },
                        { id: "sales", label: "Sales" },
                        ...(financials
                            ? [{ id: "account", label: "Account" }]
                            : []),
                        ...(isBuilder
                            ? [{ id: "clients", label: "Clients" }]
                            : []),
                        { id: "sites", label: "Sites" },
                        ...(enabled("jobs")
                            ? [{ id: "jobs", label: "Jobs" }]
                            : []),
                        ...(enabled("tickets")
                            ? [{ id: "tickets", label: "Tickets" }]
                            : []),
                        { id: "documents", label: "Documents" },
                    ]}
                />

                <div className="grid gap-4 lg:grid-cols-3">
                    <SectionCard
                        id="overview"
                        title="Contact"
                        description="Primary contact details for this customer."
                        icon={UserRound}
                        tone="info"
                    >
                        <dl className="grid gap-4 sm:grid-cols-2">
                            <DetailRow
                                label="Type"
                                value={
                                    <StatusPill
                                        tone={
                                            customer.type.is_organisation
                                                ? "violet"
                                                : "blue"
                                        }
                                    >
                                        {customer.type.label}
                                    </StatusPill>
                                }
                            />
                            <DetailRow
                                label="Status"
                                value={
                                    <StatusPill
                                        tone={
                                            customer.is_active
                                                ? "green"
                                                : "slate"
                                        }
                                    >
                                        {customer.is_active
                                            ? "Active"
                                            : "Inactive"}
                                    </StatusPill>
                                }
                            />
                            <DetailRow
                                label="Email"
                                value={
                                    customer.email ? (
                                        <a
                                            href={`mailto:${customer.email}`}
                                            className="hover:underline"
                                        >
                                            {customer.email}
                                        </a>
                                    ) : null
                                }
                            />
                            <DetailRow
                                label="Phone"
                                value={
                                    customer.phone ? (
                                        <a
                                            href={`tel:${customer.phone}`}
                                            className="hover:underline"
                                        >
                                            {customer.phone}
                                        </a>
                                    ) : null
                                }
                            />
                            <DetailRow
                                label="Alternate phone"
                                value={customer.alternate_phone}
                            />
                            <DetailRow
                                label="Preferred contact"
                                value={customer.preferred_contact_method?.label}
                            />
                            {customer.company_name ? (
                                <DetailRow
                                    label="Company"
                                    value={customer.company_name}
                                />
                            ) : null}
                        </dl>
                    </SectionCard>

                    <SectionCard
                        id="billing"
                        title="Billing address"
                        description="Where invoices are sent."
                        icon={MapPin}
                    >
                        <p className="text-sm leading-relaxed">
                            {billingAddress || "No billing address recorded."}
                        </p>
                    </SectionCard>

                    <SectionCard
                        id="sales"
                        title="Sales and ownership"
                        description="Who owns the relationship and where the lead came from."
                        icon={Target}
                        tone="amber"
                    >
                        <dl className="grid gap-4 sm:grid-cols-2">
                            <DetailRow
                                label="Account owner"
                                value={customer.owner?.name}
                            />
                            <DetailRow
                                label="Lead source"
                                value={customer.lead_source?.label}
                            />
                            <DetailRow
                                label="Lead detail"
                                value={customer.lead_source_detail}
                            />
                            <DetailRow
                                label="Customer since"
                                value={formatDate(customer.created_at)}
                            />
                        </dl>
                        {customer.notes_html ? (
                            <div className="mt-4">
                                <StaticField
                                    label="Notes"
                                    value={
                                        <RichText html={customer.notes_html} />
                                    }
                                />
                            </div>
                        ) : null}
                    </SectionCard>
                </div>

                {financials ? (
                    <SectionCard
                        id="account"
                        title="Account"
                        description="The money on this customer's jobs, and what Finance is still owed."
                        icon={Wallet}
                        tone="success"
                    >
                        <dl className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
                            <DetailRow
                                label="Sale value"
                                value={formatCurrency(
                                    financials.contract_value,
                                )}
                            />
                            <DetailRow
                                label="Deposits"
                                value={formatCurrency(financials.deposit)}
                            />
                            <DetailRow
                                label="Invoiced"
                                value={formatCurrency(financials.invoiced)}
                            />
                            <DetailRow
                                label="Outstanding"
                                value={
                                    <span
                                        className={
                                            financials.outstanding > 0
                                                ? "font-semibold text-amber-700 dark:text-amber-300"
                                                : "font-semibold text-emerald-700 dark:text-emerald-300"
                                        }
                                    >
                                        {formatCurrency(
                                            financials.outstanding,
                                        )}
                                    </span>
                                }
                            />
                        </dl>
                        <p className="mt-4 text-xs text-muted-foreground">
                            {financials.invoice_count === 0
                                ? "No invoices have been raised against this customer yet."
                                : `${formatNumber(financials.invoice_count)} invoice${financials.invoice_count === 1 ? "" : "s"}, ${formatCurrency(financials.paid)} paid.`}
                        </p>
                    </SectionCard>
                ) : null}

                {isBuilder ? (
                    <SectionCard
                        id="clients"
                        title={`Clients (${clients.length})`}
                        description="The households and businesses this builder sends work for. Each one keeps its own sites, jobs and billing."
                        icon={HardHat}
                        tone="amber"
                        flush
                        actions={
                            <>
                                {can.createClient ? (
                                    <Button variant="outline" size="sm" asChild>
                                        <Link
                                            href={customerCreate({
                                                query: {
                                                    builder_id: customer.id,
                                                },
                                            })}
                                        >
                                            <Plus />
                                            New client
                                        </Link>
                                    </Button>
                                ) : null}
                                {can.linkBuilder ? (
                                    <Dialog
                                        open={assignOpen}
                                        onOpenChange={(open) => {
                                            setAssignOpen(open);

                                            if (!open) {
                                                assign.reset();
                                                assign.clearErrors();
                                            }
                                        }}
                                    >
                                        <DialogTrigger asChild>
                                            <Button
                                                variant="outline"
                                                size="sm"
                                            >
                                                <Link2 />
                                                Assign a client
                                            </Button>
                                        </DialogTrigger>
                                        <DialogContent className="sm:max-w-lg">
                                            <DialogHeader>
                                                <DialogTitle>
                                                    Assign a client to{" "}
                                                    {customer.name}
                                                </DialogTitle>
                                                <DialogDescription>
                                                    Search the customer list.
                                                    Nothing is moved: the client
                                                    keeps their own sites, jobs
                                                    and billing, and is only
                                                    recorded as one of this
                                                    builder's clients.
                                                </DialogDescription>
                                            </DialogHeader>

                                            <FormField
                                                label="Client"
                                                htmlFor="client_id"
                                                error={
                                                    assign.errors.customer_id
                                                }
                                                required
                                                hint="A builder account cannot be a client of another builder."
                                            >
                                                <Combobox
                                                    id="client_id"
                                                    name="customer_id"
                                                    options={[]}
                                                    value={
                                                        assign.data.customer_id
                                                    }
                                                    onChange={(value) =>
                                                        assign.setData(
                                                            "customer_id",
                                                            value,
                                                        )
                                                    }
                                                    remote={{
                                                        url: customersLookup()
                                                            .url,
                                                    }}
                                                    placeholder="Search by name, phone or address"
                                                    emptyLabel="No customer matches that"
                                                />
                                            </FormField>

                                            <DialogFooter>
                                                <DialogClose asChild>
                                                    <Button
                                                        variant="outline"
                                                        size="sm"
                                                    >
                                                        Cancel
                                                    </Button>
                                                </DialogClose>
                                                <Button
                                                    size="sm"
                                                    disabled={
                                                        assign.processing ||
                                                        assign.data
                                                            .customer_id ===
                                                            null
                                                    }
                                                    onClick={() =>
                                                        assign.post(
                                                            attachClient.url(
                                                                customer.id,
                                                            ),
                                                            {
                                                                preserveScroll: true,
                                                                onSuccess: () => {
                                                                    setAssignOpen(
                                                                        false,
                                                                    );
                                                                    assign.reset();
                                                                },
                                                            },
                                                        )
                                                    }
                                                    data-test="assign-client-button"
                                                >
                                                    Assign client
                                                </Button>
                                            </DialogFooter>
                                        </DialogContent>
                                    </Dialog>
                                ) : null}
                            </>
                        }
                    >
                        {clients.length === 0 ? (
                            <EmptyState
                                icon={HardHat}
                                title="No clients under this builder yet"
                                description="Add a client to create their record under this account, or assign one that is already in the customer list."
                            />
                        ) : (
                            <Table>
                                <TableHeader>
                                    <TableRow>
                                        <TableHead className="pl-5">
                                            Client
                                        </TableHead>
                                        <TableHead>Contact</TableHead>
                                        <TableHead>Site</TableHead>
                                        <TableHead className="text-right">
                                            Jobs
                                        </TableHead>
                                        <TableHead className="pr-5 text-right">
                                            Work
                                        </TableHead>
                                    </TableRow>
                                </TableHeader>
                                <TableBody>
                                    {clients.map((client) => (
                                        <TableRow key={client.id}>
                                            <TableCell className="min-w-52 pl-5">
                                                <Link
                                                    href={customerShow(
                                                        client.id,
                                                    )}
                                                    className="text-sm font-medium hover:underline"
                                                >
                                                    {client.name}
                                                </Link>
                                                <div className="text-muted-foreground mt-0.5 font-mono text-[11px]">
                                                    {client.customer_number}
                                                </div>
                                            </TableCell>
                                            <TableCell className="min-w-44 text-sm">
                                                <div>
                                                    {client.email ?? "—"}
                                                </div>
                                                <div className="text-muted-foreground mt-0.5 text-xs">
                                                    {client.phone ?? "—"}
                                                </div>
                                            </TableCell>
                                            <TableCell className="min-w-48 text-sm">
                                                {client.primary_site ? (
                                                    <>
                                                        <div>
                                                            {
                                                                client
                                                                    .primary_site
                                                                    .address
                                                            }
                                                        </div>
                                                        <div className="text-muted-foreground mt-0.5 text-xs">
                                                            {
                                                                client
                                                                    .primary_site
                                                                    .distribution_network ??
                                                                "Network not set"
                                                            }
                                                        </div>
                                                    </>
                                                ) : (
                                                    <span className="text-muted-foreground text-xs">
                                                        No site recorded
                                                    </span>
                                                )}
                                            </TableCell>
                                            <TableCell className="text-right">
                                                <div className="crm-num text-sm font-medium">
                                                    {formatNumber(
                                                        client.active_jobs_count,
                                                    )}
                                                    <span className="text-muted-foreground ml-1 text-xs font-normal">
                                                        active
                                                    </span>
                                                </div>
                                                <div className="crm-num text-muted-foreground mt-0.5 text-xs">
                                                    {formatNumber(
                                                        client.jobs_count,
                                                    )}{" "}
                                                    total
                                                </div>
                                            </TableCell>
                                            <TableCell className="pr-5 text-right whitespace-nowrap">
                                                <div className="flex items-center justify-end gap-1">
                                                    {can.createJob ? (
                                                        <Button
                                                            variant="ghost"
                                                            size="sm"
                                                            asChild
                                                        >
                                                            <Link
                                                                href={jobCreate(
                                                                    {
                                                                        query: {
                                                                            customer:
                                                                                client.id,
                                                                        },
                                                                    },
                                                                )}
                                                            >
                                                                New job
                                                            </Link>
                                                        </Button>
                                                    ) : null}
                                                    {can.linkBuilder ? (
                                                        <Button
                                                            variant="ghost"
                                                            size="sm"
                                                            title={`Take ${client.name} off ${customer.name}`}
                                                            onClick={() => {
                                                                if (
                                                                    window.confirm(
                                                                        `Take ${client.name} off ${customer.name}? Their sites, jobs and billing stay where they are.`,
                                                                    )
                                                                ) {
                                                                    router.delete(
                                                                        detachBuilder.url(
                                                                            client.id,
                                                                        ),
                                                                        {
                                                                            preserveScroll: true,
                                                                        },
                                                                    );
                                                                }
                                                            }}
                                                        >
                                                            <Unlink />
                                                        </Button>
                                                    ) : null}
                                                </div>
                                            </TableCell>
                                        </TableRow>
                                    ))}
                                </TableBody>
                            </Table>
                        )}
                    </SectionCard>
                ) : null}

                <SectionCard
                    id="sites"
                    title={`Sites (${customer.sites.length})`}
                    description="Each installation address carries its own grid details, which decide the network and inspection rules for its jobs."
                    icon={MapPinned}
                    tone="blue"
                    actions={
                        can.createSite ? (
                            <Dialog
                                open={siteDialogOpen}
                                onOpenChange={setSiteDialogOpen}
                            >
                                <DialogTrigger asChild>
                                    <Button variant="outline" size="sm">
                                        <Plus />
                                        Add site
                                    </Button>
                                </DialogTrigger>
                                <DialogContent className="max-h-[85vh] overflow-y-auto sm:max-w-2xl">
                                    <DialogHeader>
                                        <DialogTitle>Add a site</DialogTitle>
                                        <DialogDescription>
                                            The state and distribution network
                                            determine the connection and
                                            inspection requirements for jobs at
                                            this address.
                                        </DialogDescription>
                                    </DialogHeader>

                                    <Form
                                        {...SiteController.store.form({
                                            customer: customer.id,
                                        })}
                                        options={{ preserveScroll: true }}
                                        onSuccess={() =>
                                            setSiteDialogOpen(false)
                                        }
                                        className="grid gap-4 sm:grid-cols-2"
                                    >
                                        {({ processing, errors }) => (
                                            <>
                                                <FormField
                                                    label="Label"
                                                    htmlFor="label"
                                                    error={errors.label}
                                                    hint="For example Home, Warehouse, Site 2."
                                                >
                                                    <Input
                                                        id="label"
                                                        name="label"
                                                    />
                                                </FormField>

                                                <FormField
                                                    label="State"
                                                    htmlFor="state"
                                                    error={errors.state}
                                                    required
                                                    hint="Drives the grid and inspection rules."
                                                >
                                                    <NativeSelect
                                                        id="state"
                                                        name="state"
                                                        defaultValue={
                                                            customer.billing
                                                                .state ?? ""
                                                        }
                                                        required
                                                    >
                                                        <option value="">
                                                            Select a state
                                                        </option>
                                                        {options.states.map(
                                                            (option) => (
                                                                <option
                                                                    key={
                                                                        option.value
                                                                    }
                                                                    value={
                                                                        option.value
                                                                    }
                                                                >
                                                                    {
                                                                        option.label
                                                                    }
                                                                </option>
                                                            ),
                                                        )}
                                                    </NativeSelect>
                                                </FormField>

                                                <FormField
                                                    label="Address line 1"
                                                    htmlFor="address_line1"
                                                    error={errors.address_line1}
                                                    required
                                                    className="sm:col-span-2"
                                                >
                                                    <Input
                                                        id="address_line1"
                                                        name="address_line1"
                                                        required
                                                    />
                                                </FormField>

                                                <FormField
                                                    label="Address line 2"
                                                    htmlFor="address_line2"
                                                    error={errors.address_line2}
                                                    className="sm:col-span-2"
                                                >
                                                    <Input
                                                        id="address_line2"
                                                        name="address_line2"
                                                    />
                                                </FormField>

                                                <FormField
                                                    label="Suburb"
                                                    htmlFor="suburb"
                                                    error={errors.suburb}
                                                    required
                                                >
                                                    <Input
                                                        id="suburb"
                                                        name="suburb"
                                                        required
                                                    />
                                                </FormField>

                                                <FormField
                                                    label="Postcode"
                                                    htmlFor="postcode"
                                                    error={errors.postcode}
                                                    required
                                                    hint="4 digits"
                                                >
                                                    <Input
                                                        id="postcode"
                                                        name="postcode"
                                                        inputMode="numeric"
                                                        required
                                                    />
                                                </FormField>

                                                <FormField
                                                    label="NMI"
                                                    htmlFor="nmi"
                                                    error={errors.nmi}
                                                    hint="National Metering Identifier at the connection point."
                                                >
                                                    <Input
                                                        id="nmi"
                                                        name="nmi"
                                                    />
                                                </FormField>

                                                <FormField
                                                    label="Meter number"
                                                    htmlFor="meter_number"
                                                    error={errors.meter_number}
                                                >
                                                    <Input
                                                        id="meter_number"
                                                        name="meter_number"
                                                    />
                                                </FormField>

                                                <FormField
                                                    label="Distribution network (DNSP)"
                                                    htmlFor="distribution_network_id"
                                                    error={
                                                        errors.distribution_network_id
                                                    }
                                                    className="sm:col-span-2"
                                                >
                                                    <NativeSelect
                                                        id="distribution_network_id"
                                                        name="distribution_network_id"
                                                        defaultValue=""
                                                    >
                                                        <option value="">
                                                            Not yet determined
                                                        </option>
                                                        {options.distributionNetworks.map(
                                                            (group) => (
                                                                <optgroup
                                                                    key={
                                                                        group.state
                                                                    }
                                                                    label={
                                                                        group.state_label
                                                                    }
                                                                >
                                                                    {group.networks.map(
                                                                        (
                                                                            network,
                                                                        ) => (
                                                                            <option
                                                                                key={
                                                                                    network.value
                                                                                }
                                                                                value={
                                                                                    network.value
                                                                                }
                                                                            >
                                                                                {
                                                                                    network.label
                                                                                }
                                                                            </option>
                                                                        ),
                                                                    )}
                                                                </optgroup>
                                                            ),
                                                        )}
                                                    </NativeSelect>
                                                </FormField>

                                                <FormField
                                                    label="Electricity retailer"
                                                    htmlFor="electricity_retailer"
                                                    error={
                                                        errors.electricity_retailer
                                                    }
                                                >
                                                    <Input
                                                        id="electricity_retailer"
                                                        name="electricity_retailer"
                                                    />
                                                </FormField>

                                                <FormField
                                                    label="Supply phase"
                                                    htmlFor="phase"
                                                    error={errors.phase}
                                                    required
                                                >
                                                    <NativeSelect
                                                        id="phase"
                                                        name="phase"
                                                        defaultValue="unknown"
                                                    >
                                                        {options.phases.map(
                                                            (option) => (
                                                                <option
                                                                    key={
                                                                        option.value
                                                                    }
                                                                    value={
                                                                        option.value
                                                                    }
                                                                >
                                                                    {
                                                                        option.label
                                                                    }
                                                                </option>
                                                            ),
                                                        )}
                                                    </NativeSelect>
                                                </FormField>

                                                <FormField
                                                    label="Roof type"
                                                    htmlFor="roof_type"
                                                    error={errors.roof_type}
                                                >
                                                    <NativeSelect
                                                        id="roof_type"
                                                        name="roof_type"
                                                        defaultValue=""
                                                    >
                                                        <option value="">
                                                            Not recorded
                                                        </option>
                                                        <option value="tiled">
                                                            Tiled
                                                        </option>
                                                        <option value="metal">
                                                            Metal
                                                        </option>
                                                        <option value="concrete">
                                                            Concrete
                                                        </option>
                                                        <option value="flat">
                                                            Flat / membrane
                                                        </option>
                                                    </NativeSelect>
                                                </FormField>

                                                <FormField
                                                    label="Storeys"
                                                    htmlFor="storeys"
                                                    error={errors.storeys}
                                                >
                                                    <Input
                                                        id="storeys"
                                                        name="storeys"
                                                        type="number"
                                                        min={1}
                                                        max={20}
                                                        defaultValue={1}
                                                    />
                                                </FormField>

                                                <FormField
                                                    label="Switchboard"
                                                    htmlFor="switchboard_type"
                                                    error={
                                                        errors.switchboard_type
                                                    }
                                                >
                                                    <Input
                                                        id="switchboard_type"
                                                        name="switchboard_type"
                                                        placeholder="For example ceramic fuses, newer board"
                                                    />
                                                </FormField>

                                                <FormField
                                                    label="Asbestos"
                                                    htmlFor="has_asbestos"
                                                    error={errors.has_asbestos}
                                                    hint="Flagged for the installer's risk assessment."
                                                >
                                                    <>
                                                        <input
                                                            type="hidden"
                                                            name="has_asbestos"
                                                            value="0"
                                                        />
                                                        <label
                                                            htmlFor="has_asbestos"
                                                            className="flex items-center gap-2 text-sm"
                                                        >
                                                            <input
                                                                id="has_asbestos"
                                                                name="has_asbestos"
                                                                type="checkbox"
                                                                value="1"
                                                                className="border-input size-4 rounded border"
                                                            />
                                                            Asbestos present
                                                        </label>
                                                    </>
                                                </FormField>

                                                <FormField
                                                    label="Access notes"
                                                    htmlFor="access_notes"
                                                    error={errors.access_notes}
                                                    className="sm:col-span-2"
                                                    hint="Parking, gates, dogs, where the switchboard is."
                                                >
                                                    <textarea
                                                        id="access_notes"
                                                        name="access_notes"
                                                        rows={3}
                                                        className="border-input dark:bg-input/30 focus-visible:border-ring focus-visible:ring-ring/50 w-full rounded-md border bg-transparent px-3 py-2 text-sm shadow-xs outline-none focus-visible:ring-[3px]"
                                                    />
                                                </FormField>

                                                <FormField
                                                    label="Hazard notes"
                                                    htmlFor="hazard_notes"
                                                    error={errors.hazard_notes}
                                                    className="sm:col-span-2"
                                                >
                                                    <textarea
                                                        id="hazard_notes"
                                                        name="hazard_notes"
                                                        rows={3}
                                                        className="border-input dark:bg-input/30 focus-visible:border-ring focus-visible:ring-ring/50 w-full rounded-md border bg-transparent px-3 py-2 text-sm shadow-xs outline-none focus-visible:ring-[3px]"
                                                    />
                                                </FormField>

                                                <div className="sm:col-span-2">
                                                    <FormField
                                                        label="Primary site"
                                                        htmlFor="is_primary"
                                                        error={
                                                            errors.is_primary
                                                        }
                                                    >
                                                        <>
                                                            <input
                                                                type="hidden"
                                                                name="is_primary"
                                                                value="0"
                                                            />
                                                            <label
                                                                htmlFor="is_primary"
                                                                className="flex items-center gap-2 text-sm"
                                                            >
                                                                <input
                                                                    id="is_primary"
                                                                    name="is_primary"
                                                                    type="checkbox"
                                                                    value="1"
                                                                    defaultChecked={
                                                                        customer
                                                                            .sites
                                                                            .length ===
                                                                        0
                                                                    }
                                                                    className="border-input size-4 rounded border"
                                                                />
                                                                This is the
                                                                primary site
                                                            </label>
                                                        </>
                                                    </FormField>
                                                </div>

                                                <DialogFooter className="sm:col-span-2">
                                                    <DialogClose asChild>
                                                        <Button
                                                            type="button"
                                                            variant="outline"
                                                        >
                                                            Cancel
                                                        </Button>
                                                    </DialogClose>
                                                    <Button
                                                        type="submit"
                                                        disabled={processing}
                                                    >
                                                        Save site
                                                    </Button>
                                                </DialogFooter>
                                            </>
                                        )}
                                    </Form>
                                </DialogContent>
                            </Dialog>
                        ) : null
                    }
                >
                    {customer.sites.length === 0 ? (
                        <EmptyState
                            icon={MapPinned}
                            title="No sites recorded"
                            description="Add the installation address so the network, NMI and inspection rules can be captured against the job."
                        />
                    ) : (
                        <div className="grid gap-3 lg:grid-cols-2">
                            {customer.sites.map((site) => (
                                <SiteCard
                                    key={site.id}
                                    site={site}
                                    ownerId={customer.id}
                                    ownerName={customer.name}
                                    canTransfer={can.transferOwnership}
                                    reasons={options.ownershipReasons}
                                    customerTypes={options.customerTypes}
                                />
                            ))}
                        </div>
                    )}
                </SectionCard>

                {enabled("jobs") ? (
                <SectionCard
                    id="jobs"
                    title={`Jobs (${jobs.length})`}
                    description="Every job recorded against this customer, newest first."
                    icon={BriefcaseBusiness}
                    tone="solar"
                    flush
                >
                    {jobs.length === 0 ? (
                        <EmptyState
                            icon={BriefcaseBusiness}
                            title="No jobs yet"
                            description="Create a job to start the installation pipeline for one of this customer's sites."
                            action={
                                can.createJob ? (
                                    <Button asChild>
                                        <Link
                                            href={jobCreate({
                                                query: {
                                                    customer: customer.id,
                                                },
                                            })}
                                        >
                                            New job
                                        </Link>
                                    </Button>
                                ) : null
                            }
                        />
                    ) : (
                        <Table>
                            <TableHeader>
                                <TableRow>
                                    <TableHead className="pl-5">Job</TableHead>
                                    <TableHead>Type</TableHead>
                                    <TableHead>Status</TableHead>
                                    <TableHead>Site</TableHead>
                                    <TableHead>Install date</TableHead>
                                    <TableHead className="pr-5">
                                        Owner
                                    </TableHead>
                                </TableRow>
                            </TableHeader>
                            <TableBody>
                                {jobs.map((job) => (
                                    <TableRow key={job.id}>
                                        <TableCell className="min-w-44 pl-5 whitespace-nowrap">
                                            <Link
                                                href={jobShow(job.id)}
                                                className="font-mono text-xs font-medium hover:underline"
                                            >
                                                {job.job_number}
                                            </Link>
                                            {job.title ? (
                                                <div className="text-muted-foreground text-xs">
                                                    {job.title}
                                                </div>
                                            ) : null}
                                        </TableCell>
                                        <TableCell className="text-sm">
                                            {job.type.label}
                                        </TableCell>
                                        <TableCell>
                                            <JobStatusBadge
                                                status={job.status}
                                            />
                                        </TableCell>
                                        <TableCell className="min-w-48 text-sm">
                                            <div>
                                                {job.site?.address ?? "—"}
                                            </div>
                                            <div className="text-muted-foreground text-xs">
                                                {job.site
                                                    ?.distribution_network ??
                                                    "Network not set"}
                                            </div>
                                        </TableCell>
                                        <TableCell className="text-sm whitespace-nowrap">
                                            {job.install_scheduled_for
                                                ? formatDate(
                                                      job.install_scheduled_for,
                                                  )
                                                : "Not booked"}
                                        </TableCell>
                                        <TableCell className="pr-5 text-sm">
                                            {job.owner?.name ??
                                                job.sales_rep?.name ??
                                                "—"}
                                        </TableCell>
                                    </TableRow>
                                ))}
                            </TableBody>
                        </Table>
                    )}
                </SectionCard>
                ) : null}

                {enabled("tickets") ? (
                <SectionCard
                    id="tickets"
                    title="Support tickets"
                    description="Every complaint and service request this customer has raised, newest first."
                    icon={LifeBuoy}
                    tone={ticketCounts.open > 0 ? "warning" : "slate"}
                    flush
                    bodyClassName="divide-hairline divide-y"
                    actions={
                        <>
                            <StatusPill
                                tone={
                                    ticketCounts.open > 0 ? "warning" : "slate"
                                }
                            >
                                {ticketCounts.open} open of {ticketCounts.total}
                            </StatusPill>
                            {can.createTicket ? (
                                <Button variant="outline" size="sm" asChild>
                                    <Link
                                        href={ticketsCreate({
                                            query: { customer: customer.id },
                                        })}
                                    >
                                        <Plus className="size-4" />
                                        Log ticket
                                    </Link>
                                </Button>
                            ) : null}
                        </>
                    }
                >
                    {tickets.length === 0 ? (
                        <EmptyState
                            icon={LifeBuoy}
                            title="No support tickets"
                            description="Complaints that arrive from the SMS system are matched to this customer by their number and appear here."
                            className="py-8"
                            action={
                                can.createTicket ? (
                                    <Button asChild variant="outline" size="sm">
                                        <Link
                                            href={ticketsCreate({
                                                query: {
                                                    customer: customer.id,
                                                },
                                            })}
                                        >
                                            Log ticket
                                        </Link>
                                    </Button>
                                ) : null
                            }
                        />
                    ) : (
                        tickets.map((ticket) => (
                            <CustomerTicketRow
                                key={ticket.id}
                                ticket={ticket}
                            />
                        ))
                    )}
                </SectionCard>
                ) : null}

                <SectionCard
                    id="documents"
                    title={`Documents (${documents.length})`}
                    description="Quotes, design drawings, certificates and handover paperwork."
                    icon={FileText}
                    tone="violet"
                >
                    {documents.length === 0 ? (
                        <EmptyState
                            icon={FileText}
                            title="No documents yet"
                            description="Documents uploaded against this customer's jobs appear here."
                        />
                    ) : (
                        <ul className="divide-hairline divide-y">
                            {documents.map((document) => (
                                <li
                                    key={document.id}
                                    className="flex flex-wrap items-center justify-between gap-2 py-3 first:pt-0 last:pb-0"
                                >
                                    <div className="min-w-0">
                                        <p className="truncate text-sm font-medium">
                                            {document.title}
                                        </p>
                                        <p className="text-muted-foreground text-xs">
                                            {document.category.label} ·{" "}
                                            {document.human_size} ·{" "}
                                            {formatDate(document.created_at)}
                                        </p>
                                    </div>
                                    <StatusPill
                                        tone={
                                            document.is_verified
                                                ? "green"
                                                : "slate"
                                        }
                                    >
                                        {document.is_verified
                                            ? "Verified"
                                            : "Unverified"}
                                    </StatusPill>
                                </li>
                            ))}
                        </ul>
                    )}
                </SectionCard>
            </div>
        </>
    );
}

/**
 * The grid details on a site are what decide the connection and inspection
 * rules for its jobs, so they are shown prominently.
 */
function SiteCard({
    site,
    ownerId,
    ownerName,
    canTransfer,
    reasons,
    customerTypes,
}: {
    site: SiteSummary;
    ownerId: number;
    ownerName: string;
    canTransfer: boolean;
    reasons: OptionsBundle["ownershipReasons"];
    customerTypes: OptionsBundle["customerTypes"];
}) {
    return (
        <article className="bg-surface/60 ring-hairline rounded-xl p-4 ring-1">
            <header className="flex items-start justify-between gap-2">
                <div className="min-w-0">
                    <p className="truncate text-sm font-semibold">
                        {site.label ?? "Installation address"}
                    </p>
                    <p className="text-muted-foreground mt-0.5 text-xs">
                        {site.address}
                    </p>
                </div>
                {site.is_primary ? (
                    <RuleFlag tone="solar">Primary site</RuleFlag>
                ) : null}
            </header>

            <dl className="mt-4 grid grid-cols-2 gap-x-6 gap-y-3">
                <DetailRow label="State" value={site.state_label} />
                <DetailRow label="Postcode" value={site.postcode} />
                <DetailRow
                    label="Distribution network"
                    value={site.distribution_network?.name}
                />
                <DetailRow label="Retailer" value={site.electricity_retailer} />
                <DetailRow label="NMI" value={site.nmi} />
                <DetailRow label="Phase" value={site.phase.label} />
                <DetailRow
                    label="Roof"
                    value={formatAddress([
                        site.roof.type,
                        site.roof.material,
                        site.roof.storeys
                            ? `${site.roof.storeys} storey`
                            : null,
                    ])}
                />
                <DetailRow
                    label="Asbestos"
                    value={
                        site.roof.has_asbestos ? (
                            <RuleFlag tone="danger">
                                Flagged for assessment
                            </RuleFlag>
                        ) : (
                            "No"
                        )
                    }
                />
            </dl>

            {site.access_notes_html || site.hazard_notes_html ? (
                <div className="mt-3 grid gap-3">
                    {site.access_notes_html ? (
                        <DetailRow
                            label="Access notes"
                            value={<RichText html={site.access_notes_html} />}
                        />
                    ) : null}
                    {site.hazard_notes_html ? (
                        <DetailRow
                            label="Hazard notes"
                            value={<RichText html={site.hazard_notes_html} />}
                        />
                    ) : null}
                </div>
            ) : null}

            {/* Whose house this is, and who it was. A property is sold under
                the office's feet, and the work at the address has to stay
                readable after it changes hands. */}
            <div className="border-hairline mt-4 border-t pt-3">
                <OwnershipHistory ownership={site.ownership} />

                {canTransfer ? (
                    <div className="mt-3 flex justify-end">
                        <TransferOwnershipDialog
                            ownerId={ownerId}
                            site={{
                                id: site.id,
                                label: site.label,
                                address: site.address,
                            }}
                            currentOwnerName={ownerName}
                            reasons={reasons}
                            customerTypes={customerTypes}
                        />
                    </div>
                ) : null}
            </div>
        </article>
    );
}

/**
 * One ticket in the flushed support card: what was reported, where it is up to,
 * who owns it and how long it has been open.
 */
function CustomerTicketRow({ ticket }: { ticket: TicketSummary }) {
    const isClosed = ticket.status.is_terminal;

    return (
        <Link
            href={ticketShow(ticket.id).url}
            className="hover:bg-accent/40 flex flex-col gap-2 px-5 py-3.5 transition-colors lg:flex-row lg:items-center lg:gap-4"
        >
            <div className="flex min-w-0 flex-1 items-start gap-3">
                <StatusDot
                    tone={ticket.status.color}
                    className={cn("mt-1.5", isClosed && "opacity-50")}
                />

                <div className="min-w-0">
                    <div className="flex flex-wrap items-baseline gap-x-2 gap-y-0.5">
                        <span className="font-mono text-xs font-medium">
                            {ticket.display_number}
                        </span>
                        <span
                            className={cn(
                                "truncate text-sm font-medium",
                                isClosed && "text-muted-foreground",
                            )}
                        >
                            {ticket.issue}
                        </span>
                    </div>

                    <div className="text-muted-foreground mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs">
                        <StatusLabel
                            tone={ticket.status.color}
                            quiet={isClosed}
                            className="text-xs"
                        >
                            {ticket.status.label}
                        </StatusLabel>
                        <span aria-hidden className="text-muted-foreground/40">
                            ·
                        </span>
                        {/* Not a link: the whole row already links to the
                            ticket, and an anchor inside an anchor is invalid. */}
                        {ticket.job ? (
                            <span className="font-mono text-[11px]">
                                {ticket.job.job_number}
                            </span>
                        ) : (
                            <span>No job linked</span>
                        )}
                        <span aria-hidden className="text-muted-foreground/40">
                            ·
                        </span>
                        <span>{ticket.installer?.name ?? "Unassigned"}</span>
                    </div>
                </div>
            </div>

            <div className="flex shrink-0 flex-wrap items-center gap-2 lg:justify-end">
                <StatusPill
                    tone={ticket.priority.color}
                    className="text-[11px]"
                >
                    {ticket.priority.label}
                </StatusPill>
                <span
                    className={cn(
                        "crm-num text-xs font-medium",
                        ticket.is_overdue
                            ? "text-danger"
                            : "text-muted-foreground",
                    )}
                >
                    {formatDuration(ticket.days_open)}
                </span>
                {ticket.is_overdue ? (
                    <StatusPill tone="danger">Overdue</StatusPill>
                ) : null}
            </div>
        </Link>
    );
}

CustomerShow.layout = {
    breadcrumbs: [
        { title: "Customers", href: customersIndex() },
        { title: "Customer", href: "" },
    ],
};
