import { Head, router, useForm } from '@inertiajs/react';
import {
    CalendarPlus,
    Check,
    Copy,
    ExternalLink,
    KeyRound,
    Link2,
    Power,
    ShieldAlert,
    ShieldCheck,
    Trash2,
    UserPlus,
} from 'lucide-react';
import { useState } from 'react';
import { Callout, SectionCard } from '@/components/crm/page-header';
import { StatusPill } from '@/components/crm/status-badge';
import { FormField } from '@/components/crm/native-select';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Spinner } from '@/components/ui/spinner';
import { formatDateTime, formatRelative } from '@/lib/format';
import { cn } from '@/lib/utils';
import type { TicketStatusLink, TicketStatusLinksProps } from '@/types';

/**
 * Settings -> Status link.
 *
 * Issues the credential the office hands to a crew, and is the one place a link
 * is paused, extended, re-issued or deleted. The password exists in readable
 * form exactly once — on the screen the browser lands on after issuing it — so
 * the panel that shows it says so and offers nothing else.
 */
export default function TicketStatusLinks({
    links,
    statuses,
    defaults,
    issued,
    board,
    staff_login: staffLogin,
    can,
}: TicketStatusLinksProps) {
    const form = useForm<{
        name: string;
        username: string;
        days: number;
        statuses: string[];
    }>({
        name: '',
        username: '',
        days: defaults.days,
        statuses: [defaults.landing_status],
    });

    const submit = () => {
        form.post('/settings/status-links', {
            preserveScroll: true,
            onSuccess: () => form.reset('name', 'username'),
        });
    };

    return (
        <>
            <Head title="Status link" />

            <Callout
                tone="info"
                icon={Link2}
                title="A board for people who should not have a CRM account"
            >
                A status link is its own username and password, issued here and
                revoked here. It opens the installer-facing ticket queue — no
                prices and no customer history — where a crew can add a note or
                say the work is done. Completing a ticket stays with an Admin.
                The office can switch a link off at any moment, and every link
                expires on its own unless it is given a fresh date.
            </Callout>

            {issued ? <IssuedPanel issued={issued} /> : null}

            <SectionCard
                title="Issue a link"
                description="Give it a name you will recognise later — the crew, the shift or the month it was issued for."
                icon={UserPlus}
                tone="solar"
            >
                <form
                    className="grid gap-4"
                    onSubmit={(event) => {
                        event.preventDefault();
                        submit();
                    }}
                >
                    <div className="grid gap-4 sm:grid-cols-2">
                        <FormField
                            label="What it is for"
                            htmlFor="status-link-name"
                            error={form.errors.name}
                            required
                        >
                            <Input
                                id="status-link-name"
                                value={form.data.name}
                                placeholder="Northside install crew"
                                onChange={(event) =>
                                    form.setData('name', event.target.value)
                                }
                            />
                        </FormField>

                        <FormField
                            label="Username"
                            htmlFor="status-link-username"
                            error={form.errors.username}
                            hint="Letters, numbers, dots, dashes"
                            required
                        >
                            <Input
                                id="status-link-username"
                                value={form.data.username}
                                autoCapitalize="none"
                                autoCorrect="off"
                                spellCheck={false}
                                placeholder="northside-crew"
                                onChange={(event) =>
                                    form.setData('username', event.target.value)
                                }
                            />
                        </FormField>
                    </div>

                    <FormField
                        label="How long it lasts"
                        htmlFor="status-link-days"
                        error={form.errors.days}
                        hint="0 keeps it on until somebody switches it off"
                    >
                        <div className="flex items-center gap-2">
                            <Input
                                id="status-link-days"
                                type="number"
                                min={0}
                                max={365}
                                value={form.data.days}
                                className="w-24"
                                onChange={(event) =>
                                    form.setData(
                                        'days',
                                        Number(event.target.value),
                                    )
                                }
                            />
                            <span className="text-muted-foreground text-xs">
                                {form.data.days > 0
                                    ? `Stops working ${new Date(Date.now() + form.data.days * 86400000).toLocaleDateString('en-AU', { day: 'numeric', month: 'short', year: 'numeric' })}`
                                    : 'No end date — pause it by hand'}
                            </span>
                        </div>
                    </FormField>

                    <div className="grid gap-2">
                        <Label>What it may read</Label>
                        <p className="text-muted-foreground text-xs">
                            The board opens on the first one ticked. A crew link
                            is meant to open on the installer queue.
                        </p>

                        <div className="mt-1 grid gap-2 sm:grid-cols-2">
                            {statuses.map((status) => {
                                const checked = form.data.statuses.includes(
                                    status.value,
                                );

                                return (
                                    <label
                                        key={status.value}
                                        className={cn(
                                            'ring-hairline flex cursor-pointer items-start gap-2.5 rounded-lg px-3 py-2 ring-1 transition-colors',
                                            checked
                                                ? 'bg-solar-soft/50 ring-solar/30'
                                                : 'hover:bg-accent/40',
                                        )}
                                    >
                                        <Checkbox
                                            className="mt-0.5"
                                            checked={checked}
                                            onCheckedChange={(next) => {
                                                const values =
                                                    form.data.statuses;

                                                form.setData(
                                                    'statuses',
                                                    next === true
                                                        ? [
                                                              ...values.filter(
                                                                  (value) =>
                                                                      value !==
                                                                      status.value,
                                                              ),
                                                              status.value,
                                                          ]
                                                        : values.filter(
                                                              (value) =>
                                                                  value !==
                                                                  status.value,
                                                          ),
                                                );
                                            }}
                                        />
                                        <span className="min-w-0">
                                            <span className="block text-[13px] font-medium">
                                                {status.label}
                                            </span>
                                            <span className="text-muted-foreground mt-0.5 block text-[11px] leading-snug">
                                                {status.description}
                                            </span>
                                        </span>
                                    </label>
                                );
                            })}
                        </div>

                        {form.errors.statuses ? (
                            <p className="text-danger text-xs font-medium">
                                {form.errors.statuses}
                            </p>
                        ) : null}
                    </div>

                    <div className="flex flex-wrap items-center gap-3 border-t border-hairline pt-4">
                        <Button
                            type="submit"
                            disabled={
                                form.processing ||
                                form.data.name.trim() === '' ||
                                form.data.username.trim() === '' ||
                                form.data.statuses.length === 0
                            }
                        >
                            {form.processing ? <Spinner /> : <KeyRound />}
                            Issue the link
                        </Button>
                        <span className="text-muted-foreground text-xs">
                            A password is generated and shown once, here, when
                            the link is created.
                        </span>
                    </div>
                </form>
            </SectionCard>

            <SectionCard
                title={`Links issued (${links.length})`}
                description="Pause is instant: anybody signed in with that link is put back on the sign-in screen at their next page."
                icon={ShieldAlert}
                tone="slate"
                flush
            >
                {links.length === 0 ? (
                    <div className="px-5 pb-5">
                        <p className="text-sm text-muted-foreground">
                            No links issued yet. Create one above and hand the
                            details to the crew.
                        </p>
                    </div>
                ) : (
                    <ul className="divide-y divide-hairline">
                        {links.map((link) => (
                            <LinkRow key={link.id} link={link} />
                        ))}
                    </ul>
                )}
            </SectionCard>

            <StaffSignIn allowed={staffLogin} />

            {can.manage_board ? <BoardActions board={board} /> : null}

            <p className="text-muted-foreground px-1 text-xs leading-relaxed">
                The board lives at{' '}
                <span className="font-mono text-foreground">
                    {defaults.url}
                </span>
                . Everybody signs in there with their own username, so a crew
                that loses its details gets a new link rather than somebody
                else's password.
            </p>
        </>
    );
}

/**
 * Whether the board's sign-in screen offers a staff door at all.
 *
 * Off is where it starts: the board is a link the office hands out, and a
 * password form for company accounts is not something to publish by default.
 * A colleague who is already signed in to the CRM still walks straight in, so
 * hiding it costs staff nothing — it only removes the second way of typing the
 * same details at the board.
 */
function StaffSignIn({ allowed }: { allowed: boolean }) {
    const form = useForm({ allowed });

    return (
        <SectionCard
            title="Staff sign-in on the board"
            description="Hiding it removes the email and password tab. The issued link is unaffected, and a colleague signed in to the CRM still opens the board."
            icon={ShieldCheck}
            tone="slate"
        >
            <label
                className={cn(
                    'ring-hairline flex cursor-pointer items-start gap-2.5 rounded-lg px-3 py-2 ring-1 transition-colors',
                    form.data.allowed
                        ? 'bg-solar-soft/40 ring-solar/25'
                        : 'hover:bg-accent/40',
                )}
            >
                <Checkbox
                    className="mt-0.5"
                    checked={form.data.allowed}
                    onCheckedChange={(next) =>
                        form.setData('allowed', next === true)
                    }
                />
                <span className="min-w-0">
                    <span className="block text-[13px] font-medium">
                        Show the staff login tab
                    </span>
                    <span className="text-muted-foreground mt-0.5 block text-[11px] leading-snug">
                        {form.data.allowed
                            ? 'The board asks for a CRM email and password, and has a shared link tab beside it.'
                            : 'The board asks only for a username and password from the office.'}
                    </span>
                </span>
            </label>

            <div className="border-hairline mt-4 flex flex-wrap items-center gap-3 border-t pt-3">
                <Button
                    type="button"
                    size="sm"
                    onClick={() =>
                        form.put('/settings/status-links/staff-login', {
                            preserveScroll: true,
                        })
                    }
                    disabled={form.processing}
                >
                    {form.processing ? <Spinner /> : <Power />}
                    Save
                </Button>
                <span className="text-muted-foreground text-xs">
                    Switched off, the request is refused too, so a form left
                    open in a tab stops working.
                </span>
            </div>
        </SectionCard>
    );
}

/**
 * What the board may do to a ticket, switched here rather than deployed.
 *
 * The board is read by crews outside the office, so the office needs a way to
 * stop them changing anything without having to revoke every link. These three
 * switches are Admin and Super Admin only.
 */
function BoardActions({
    board,
}: {
    board: { notes: boolean; review: boolean; complete: boolean };
}) {
    const form = useForm({
        notes: board.notes,
        review: board.review,
        complete: board.complete,
    });

    const rows = [
        {
            key: 'notes' as const,
            title: 'Add a note',
            description:
                'A crew or a colleague can add a note to a ticket from the board. It lands in the ticket\u2019s own history, with their name against it.',
        },
        {
            key: 'review' as const,
            title: 'Send for review',
            description:
                'A crew can say the work is done and ask for it to be checked. Nothing moves until an Admin or Super Admin approves it.',
        },
        {
            key: 'complete' as const,
            title: 'Complete a reviewed ticket',
            description:
                'An Admin or Super Admin can complete a ticket that is waiting on review, recording the outcome and who signed it.',
        },
    ];

    return (
        <SectionCard
            title="What the board can change"
            description="Switched off, the button disappears and the request is refused — a shared link cannot work around it."
            icon={Power}
            tone="amber"
        >
            <div className="grid gap-2">
                {rows.map((row) => (
                    <label
                        key={row.key}
                        className={cn(
                            'ring-hairline flex cursor-pointer items-start gap-2.5 rounded-lg px-3 py-2 ring-1 transition-colors',
                            form.data[row.key]
                                ? 'bg-solar-soft/40 ring-solar/25'
                                : 'hover:bg-accent/40',
                        )}
                    >
                        <Checkbox
                            className="mt-0.5"
                            checked={form.data[row.key]}
                            onCheckedChange={(next) =>
                                form.setData(row.key, next === true)
                            }
                        />
                        <span className="min-w-0">
                            <span className="block text-[13px] font-medium">
                                {row.title}
                            </span>
                            <span className="text-muted-foreground mt-0.5 block text-[11px] leading-snug">
                                {row.description}
                            </span>
                        </span>
                    </label>
                ))}
            </div>

            <div className="border-hairline mt-4 flex flex-wrap items-center gap-3 border-t pt-3">
                <Button
                    type="button"
                    size="sm"
                    onClick={() =>
                        form.put('/settings/status-links/board', {
                            preserveScroll: true,
                        })
                    }
                    disabled={form.processing}
                >
                    {form.processing ? <Spinner /> : <Power />}
                    Save
                </Button>
                <span className="text-muted-foreground text-xs">
                    Admin and Super Admin only \u2014 a status link never has this
                    screen.
                </span>
            </div>
        </SectionCard>
    );
}

/**
 * The one moment a password is readable. It is not stored anywhere the office
 * can open again, so the panel is loud about copying it now.
 */
function IssuedPanel({
    issued,
}: {
    issued: NonNullable<TicketStatusLinksProps['issued']>;
}) {
    const [copied, setCopied] = useState<string | null>(null);

    const copy = (label: string, value: string) => {
        void navigator.clipboard?.writeText(value).then(() => {
            setCopied(label);
            window.setTimeout(() => setCopied(null), 1800);
        });
    };

    return (
        <div className="ring-solar/30 bg-solar-soft/60 rounded-xl px-4 py-4 ring-1">
            <div className="flex flex-wrap items-baseline justify-between gap-x-3 gap-y-1">
                <h2 className="text-sm font-semibold">
                    {issued.name} is ready
                </h2>
                <span className="text-muted-foreground text-[11px]">
                    This password is shown once. Copy it before you leave the
                    page.
                </span>
            </div>

            <dl className="mt-3 grid gap-2 sm:grid-cols-3">
                {[
                    { label: 'Board', value: issued.url },
                    { label: 'Username', value: issued.username },
                    { label: 'Password', value: issued.password },
                ].map((item) => (
                    <div
                        key={item.label}
                        className="bg-card ring-hairline rounded-lg px-3 py-2 ring-1"
                    >
                        <dt className="text-muted-foreground text-[10px] font-medium tracking-wide uppercase">
                            {item.label}
                        </dt>
                        <dd className="mt-0.5 flex items-center justify-between gap-2">
                            <span className="crm-num truncate font-mono text-xs font-medium">
                                {item.value}
                            </span>
                            <button
                                type="button"
                                onClick={() => copy(item.label, item.value)}
                                aria-label={`Copy ${item.label.toLowerCase()}`}
                                className="text-muted-foreground hover:text-foreground shrink-0 rounded p-1"
                            >
                                {copied === item.label ? (
                                    <Check className="text-success size-3.5" />
                                ) : (
                                    <Copy className="size-3.5" />
                                )}
                            </button>
                        </dd>
                    </div>
                ))}
            </dl>
        </div>
    );
}

function LinkRow({ link }: { link: TicketStatusLink }) {
    const [copied, setCopied] = useState(false);
    const [busy, setBusy] = useState(false);

    const patch = (data: Record<string, string | number | boolean>) => {
        setBusy(true);
        router.put(`/settings/status-links/${link.id}`, data, {
            preserveScroll: true,
            onFinish: () => setBusy(false),
        });
    };

    const act = (run: (finish: () => void) => void) => {
        setBusy(true);
        run(() => setBusy(false));
    };

    return (
        <li className="px-5 py-3.5">
            <div className="flex flex-wrap items-start justify-between gap-x-4 gap-y-2">
                <div className="min-w-0 flex-1">
                    <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
                        <span className="text-sm font-medium">{link.name}</span>
                        <StatusPill tone={link.state.color}>
                            {link.state.label}
                        </StatusPill>
                        <span className="crm-num text-muted-foreground font-mono text-[11px]">
                            {link.username}
                        </span>
                    </div>

                    <div className="mt-1 flex flex-wrap items-center gap-1">
                        {link.statuses.map((status) => (
                            <StatusPill
                                key={status.value}
                                tone={status.color}
                                className="text-[10px]"
                            >
                                {status.label}
                            </StatusPill>
                        ))}
                    </div>

                    <p className="text-muted-foreground mt-1 text-[11px]">
                        {link.expires_at
                            ? `Stops ${formatDateTime(link.expires_at)}`
                            : 'No end date'}
                        {' · '}
                        {link.last_used_at
                            ? `Last used ${formatRelative(link.last_used_at)}${link.last_used_ip ? ` from ${link.last_used_ip}` : ''}`
                            : 'Never used'}
                    </p>
                </div>

                <div className="flex flex-wrap items-center gap-1.5">
                    <Button
                        type="button"
                        variant="ghost"
                        size="sm"
                        onClick={() => {
                            void navigator.clipboard
                                ?.writeText(link.url)
                                .then(() => {
                                    setCopied(true);
                                    window.setTimeout(
                                        () => setCopied(false),
                                        1800,
                                    );
                                });
                        }}
                    >
                        {copied ? <Check className="text-success" /> : <Copy />}
                        <span className="hidden sm:inline">
                            {copied ? 'Copied' : 'Copy link'}
                        </span>
                    </Button>

                    <Button
                        type="button"
                        variant="ghost"
                        size="sm"
                        asChild
                    >
                        <a href={link.url} target="_blank" rel="noreferrer">
                            <ExternalLink />
                            <span className="hidden sm:inline">Open</span>
                        </a>
                    </Button>

                    <Button
                        type="button"
                        variant="outline"
                        size="sm"
                        disabled={busy}
                        onClick={() => patch({ is_active: !link.is_active })}
                    >
                        <Power />
                        {link.is_active ? 'Switch off' : 'Switch on'}
                    </Button>

                    <Button
                        type="button"
                        variant="ghost"
                        size="sm"
                        disabled={busy}
                        onClick={() => patch({ days: 14 })}
                    >
                        <CalendarPlus />
                        <span className="hidden sm:inline">+14 days</span>
                    </Button>

                    <Button
                        type="button"
                        variant="ghost"
                        size="sm"
                        disabled={busy}
                        onClick={() => {
                            if (
                                !window.confirm(
                                    `Issue a new password for ${link.name}? The current one stops working immediately.`,
                                )
                            ) {
                                return;
                            }

                            act((finish) =>
                                router.post(
                                    `/settings/status-links/${link.id}/password`,
                                    {},
                                    { preserveScroll: true, onFinish: finish },
                                ),
                            );
                        }}
                    >
                        <KeyRound />
                        <span className="hidden sm:inline">New password</span>
                    </Button>

                    <Button
                        type="button"
                        variant="ghost"
                        size="sm"
                        disabled={busy}
                        onClick={() => {
                            if (
                                !window.confirm(
                                    `Delete ${link.name}? Anybody using it is signed out and the credential is gone.`,
                                )
                            ) {
                                return;
                            }

                            act((finish) =>
                                router.delete(
                                    `/settings/status-links/${link.id}`,
                                    { preserveScroll: true, onFinish: finish },
                                ),
                            );
                        }}
                    >
                        <Trash2 />
                    </Button>
                </div>
            </div>
        </li>
    );
}
