import { Form, Head, Link } from '@inertiajs/react';
import { CheckCircle2, Clock, Info, ShieldCheck, XCircle } from 'lucide-react';
import { toneClasses } from '@/components/crm/tone';
import InputError from '@/components/input-error';
import { TicketCard } from '@/components/ticket/ticket-ui';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Spinner } from '@/components/ui/spinner';
import { formatDate } from '@/lib/format';
import type {
    CustomerChangeRequest,
    CustomerChangeRow,
    CustomerProfileDetails,
    Option,
} from '@/types';

type Props = {
    account: {
        name: string;
        email: string;
    };
    details: CustomerProfileDetails;
    customer: {
        customer_number: string;
        name: string;
    } | null;
    pending: CustomerChangeRequest | null;
    lastReviewed: CustomerChangeRequest | null;
    states: Option[];
};

const selectClassName =
    'border-input h-9 w-full rounded-md border bg-transparent px-3 text-sm shadow-xs outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]';

/**
 * The customer's own details.
 *
 * The page is deliberately explicit that saving here is a request, not a
 * change: the record below the form is what is in force until our team
 * approves, and the panel at the top says where the last request got to. A
 * customer who saves again while an earlier request is open replaces it rather
 * than queueing behind it.
 */
export default function TicketProfile({
    account,
    details,
    customer,
    pending,
    lastReviewed,
    states,
}: Props) {
    return (
        <>
            <Head title="Your details" />

            <div className="mx-auto w-full max-w-3xl">
                <div>
                    <p className="text-xs font-medium tracking-wide text-muted-foreground uppercase">
                        {customer?.customer_number ?? 'Your account'}
                    </p>
                    <h1 className="mt-1 text-2xl font-semibold tracking-tight sm:text-3xl">
                        Your details
                    </h1>
                    <p className="mt-1 text-sm text-muted-foreground">
                        Keep your name, contact details and postal address up
                        to date. Every change is checked by our team before it
                        goes on your record.
                    </p>
                </div>

                {pending ? (
                    <PendingPanel request={pending} />
                ) : lastReviewed ? (
                    <OutcomePanel request={lastReviewed} />
                ) : null}

                <div className="mt-6 flex items-start gap-2.5 rounded-xl bg-solar-soft/60 p-4 text-xs leading-relaxed text-foreground ring-1 ring-solar/20">
                    <ShieldCheck className="mt-0.5 size-4 shrink-0 text-solar-ink" />
                    <p>
                        You can save any correction now — we hold it for you
                        straight away. A person on our team reviews it, usually
                        the same working day, and your details update once it is
                        approved. If we cannot approve something we will tell you
                        why here.
                    </p>
                </div>

                <TicketCard
                    className="mt-4"
                    title="What we have on file"
                    description={
                        customer
                            ? `These are the details we use when we contact you about ${customer.name === account.name ? 'your system' : customer.name}.`
                            : undefined
                    }
                >
                    <Form
                        action="/ticket/details"
                        method="put"
                        className="flex flex-col gap-5"
                    >
                        {({ processing, errors }) => (
                            <>
                                <div className="grid gap-4 sm:grid-cols-2">
                                    <div className="grid gap-2">
                                        <Label htmlFor="first_name">
                                            First name
                                        </Label>
                                        <Input
                                            id="first_name"
                                            name="first_name"
                                            required
                                            autoComplete="given-name"
                                            defaultValue={
                                                details.first_name ?? ''
                                            }
                                        />
                                        <InputError
                                            message={errors.first_name}
                                        />
                                    </div>

                                    <div className="grid gap-2">
                                        <Label htmlFor="last_name">
                                            Last name
                                        </Label>
                                        <Input
                                            id="last_name"
                                            name="last_name"
                                            autoComplete="family-name"
                                            defaultValue={
                                                details.last_name ?? ''
                                            }
                                        />
                                        <InputError
                                            message={errors.last_name}
                                        />
                                    </div>

                                    <div className="grid gap-2">
                                        <Label htmlFor="email">
                                            Email address
                                        </Label>
                                        <Input
                                            id="email"
                                            name="email"
                                            type="email"
                                            required
                                            autoComplete="email"
                                            defaultValue={details.email ?? ''}
                                        />
                                        <p className="text-xs text-muted-foreground">
                                            This is also how you sign in. If it
                                            changes, we will email the new
                                            address for you to confirm.
                                        </p>
                                        <InputError message={errors.email} />
                                    </div>

                                    <div className="grid gap-2">
                                        <Label htmlFor="phone">
                                            Mobile or phone
                                        </Label>
                                        <Input
                                            id="phone"
                                            name="phone"
                                            type="tel"
                                            required
                                            autoComplete="tel"
                                            defaultValue={details.phone ?? ''}
                                        />
                                        <InputError message={errors.phone} />
                                    </div>

                                    <div className="grid gap-2">
                                        <Label htmlFor="alternate_phone">
                                            Alternate phone
                                        </Label>
                                        <Input
                                            id="alternate_phone"
                                            name="alternate_phone"
                                            type="tel"
                                            defaultValue={
                                                details.alternate_phone ?? ''
                                            }
                                        />
                                        <InputError
                                            message={errors.alternate_phone}
                                        />
                                    </div>
                                </div>

                                <div className="rounded-xl bg-muted/50 p-4">
                                    <p className="text-xs font-medium">
                                        Postal address
                                    </p>
                                    <p className="mt-1 text-xs text-muted-foreground">
                                        Where we send paperwork and invoices.
                                        The address of the installation is
                                        changed by our team — report it below
                                        and we will sort it out.
                                    </p>

                                    <div className="mt-3 grid gap-3 sm:grid-cols-2">
                                        <div className="grid gap-2 sm:col-span-2">
                                            <Label htmlFor="billing_address_line1">
                                                Street address
                                            </Label>
                                            <Input
                                                id="billing_address_line1"
                                                name="billing_address_line1"
                                                autoComplete="address-line1"
                                                defaultValue={
                                                    details.billing_address_line1 ??
                                                    ''
                                                }
                                            />
                                            <InputError
                                                message={
                                                    errors.billing_address_line1
                                                }
                                            />
                                        </div>

                                        <div className="grid gap-2 sm:col-span-2">
                                            <Label htmlFor="billing_address_line2">
                                                Unit, building or level
                                            </Label>
                                            <Input
                                                id="billing_address_line2"
                                                name="billing_address_line2"
                                                autoComplete="address-line2"
                                                defaultValue={
                                                    details.billing_address_line2 ??
                                                    ''
                                                }
                                            />
                                            <InputError
                                                message={
                                                    errors.billing_address_line2
                                                }
                                            />
                                        </div>

                                        <div className="grid gap-2">
                                            <Label htmlFor="billing_suburb">
                                                Suburb
                                            </Label>
                                            <Input
                                                id="billing_suburb"
                                                name="billing_suburb"
                                                autoComplete="address-level2"
                                                defaultValue={
                                                    details.billing_suburb ?? ''
                                                }
                                            />
                                            <InputError
                                                message={errors.billing_suburb}
                                            />
                                        </div>

                                        <div className="grid grid-cols-2 gap-3">
                                            <div className="grid gap-2">
                                                <Label htmlFor="billing_state">
                                                    State
                                                </Label>
                                                <select
                                                    id="billing_state"
                                                    name="billing_state"
                                                    className={selectClassName}
                                                    defaultValue={
                                                        details.billing_state ??
                                                        ''
                                                    }
                                                >
                                                    <option value="">
                                                        Select
                                                    </option>
                                                    {states.map((state) => (
                                                        <option
                                                            key={state.value}
                                                            value={state.value}
                                                        >
                                                            {state.label}
                                                        </option>
                                                    ))}
                                                </select>
                                                <InputError
                                                    message={
                                                        errors.billing_state
                                                    }
                                                />
                                            </div>

                                            <div className="grid gap-2">
                                                <Label htmlFor="billing_postcode">
                                                    Postcode
                                                </Label>
                                                <Input
                                                    id="billing_postcode"
                                                    name="billing_postcode"
                                                    inputMode="numeric"
                                                    autoComplete="postal-code"
                                                    defaultValue={
                                                        details.billing_postcode ??
                                                        ''
                                                    }
                                                />
                                                <InputError
                                                    message={
                                                        errors.billing_postcode
                                                    }
                                                />
                                            </div>
                                        </div>
                                    </div>
                                </div>

                                <div className="grid gap-2">
                                    <Label htmlFor="customer_note">
                                        Anything we should know? (optional)
                                    </Label>
                                    <textarea
                                        id="customer_note"
                                        name="customer_note"
                                        maxLength={1000}
                                        className="border-input min-h-24 w-full rounded-md border bg-transparent px-3 py-2 text-sm shadow-xs outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]"
                                        placeholder="For example: this is my married name, or we have moved and this is the new postal address."
                                    />
                                    <InputError message={errors.customer_note} />
                                </div>

                                <div className="flex flex-wrap items-center gap-3">
                                    <Button
                                        type="submit"
                                        disabled={processing}
                                    >
                                        {processing && <Spinner />}
                                        Save for approval
                                    </Button>
                                    <p className="text-xs text-muted-foreground">
                                        Nothing changes on your record until
                                        our team approves it.
                                    </p>
                                </div>
                            </>
                        )}
                    </Form>
                </TicketCard>

                <div className="mt-5 flex items-start gap-2 text-xs leading-relaxed text-muted-foreground">
                    <Info className="mt-0.5 size-3.5 shrink-0" />
                    <p>
                        Need the installation address, the system details or the
                        name on the account changed?{' '}
                        <Link
                            href="/ticket/tickets/new"
                            className="font-medium text-foreground underline underline-offset-4"
                        >
                            Report it
                        </Link>{' '}
                        and the support team will take care of it.
                    </p>
                </div>
            </div>
        </>
    );
}

/** A request that is still in the queue. */
function PendingPanel({ request }: { request: CustomerChangeRequest }) {
    return (
        <section className="mt-6 rounded-2xl border border-amber-500/25 bg-amber-500/[0.07] p-5">
            <div className="flex flex-wrap items-center justify-between gap-2">
                <p className="inline-flex items-center gap-2 text-sm font-semibold text-amber-900 dark:text-amber-200">
                    <Clock className="size-4" />
                    Waiting for our team to approve
                </p>
                {request.submitted_at ? (
                    <p className="text-xs text-muted-foreground">
                        Saved {formatDate(request.submitted_at)}
                    </p>
                ) : null}
            </div>

            <p className="mt-1 text-xs leading-relaxed text-muted-foreground">
                Your saved details are below. We have your correction and will
                confirm it — your record stays as it is until then.
            </p>

            <ChangeRows changes={request.changes} className="mt-3" />

            {request.customer_note ? (
                <p className="mt-3 rounded-lg bg-background/60 px-3 py-2 text-xs leading-relaxed">
                    <span className="font-medium">Your note: </span>
                    {request.customer_note}
                </p>
            ) : null}
        </section>
    );
}

/** The answer to the most recent request, so the customer is never left guessing. */
function OutcomePanel({ request }: { request: CustomerChangeRequest }) {
    const approved = request.status.value === 'approved';

    return (
        <section
            className={`mt-6 rounded-2xl p-5 ring-1 ${
                approved
                    ? 'bg-emerald-500/[0.07] ring-emerald-500/25'
                    : 'bg-red-500/[0.06] ring-red-500/25'
            }`}
        >
            <div className="flex flex-wrap items-center justify-between gap-2">
                <p
                    className={`inline-flex items-center gap-2 text-sm font-semibold ${
                        approved
                            ? 'text-emerald-900 dark:text-emerald-200'
                            : 'text-red-900 dark:text-red-200'
                    }`}
                >
                    {approved ? (
                        <CheckCircle2 className="size-4" />
                    ) : (
                        <XCircle className="size-4" />
                    )}
                    {approved
                        ? 'Your last change was approved'
                        : 'Your last change was declined'}
                </p>
                {request.reviewed_at ? (
                    <p className="text-xs text-muted-foreground">
                        {formatDate(request.reviewed_at)}
                    </p>
                ) : null}
            </div>

            <div className="mt-2">
                <span
                    className={`inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium ${toneClasses(request.status.tone).pill}`}
                >
                    {request.status.label}
                </span>
            </div>

            {request.changes.length > 0 ? (
                <ChangeRows changes={request.changes} className="mt-3" />
            ) : null}

            {request.review_note ? (
                <p className="mt-3 rounded-lg bg-background/60 px-3 py-2 text-xs leading-relaxed">
                    <span className="font-medium">From our team: </span>
                    {request.review_note}
                </p>
            ) : null}
        </section>
    );
}

/** What was asked for, field by field, with the old value kept visible. */
function ChangeRows({
    changes,
    className,
}: {
    changes: CustomerChangeRow[];
    className?: string;
}) {
    if (changes.length === 0) {
        return null;
    }

    return (
        <dl
            className={`divide-y divide-hairline/70 overflow-hidden rounded-xl bg-background/60 ${className ?? ''}`}
        >
            {changes.map((change) => (
                <div
                    key={change.field}
                    className="flex flex-wrap items-baseline justify-between gap-x-4 gap-y-1 px-3 py-2 text-xs"
                >
                    <dt className="font-medium text-muted-foreground">
                        {change.label}
                    </dt>
                    <dd className="flex flex-wrap items-baseline gap-2">
                        <span className="text-muted-foreground line-through">
                            {change.from ?? '—'}
                        </span>
                        <span aria-hidden className="text-muted-foreground">
                            →
                        </span>
                        <span className="font-medium">{change.to ?? '—'}</span>
                    </dd>
                </div>
            ))}
        </dl>
    );
}
