import { Head, useForm } from '@inertiajs/react';
import {
    Building2,
    CheckCircle2,
    GitBranch,
    Layers,
    LifeBuoy,
    ShieldCheck,
    Wallet,
} from 'lucide-react';
import type { LucideIcon } from 'lucide-react';
import { Callout, PageHeader, SectionCard } from '@/components/crm/page-header';
import { FormActions } from '@/components/crm/form-field';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Label } from '@/components/ui/label';
import { Spinner } from '@/components/ui/spinner';
import { cn } from '@/lib/utils';
import type {
    ReleaseHistoryEntry,
    ReleasePart,
    ReleaseState,
} from '@/types';

type ReleasePageProps = {
    release: ReleaseState;
    history: ReleaseHistoryEntry[];
    version: {
        number: string;
        label: string;
        recorded: string | null;
    };
    can: { manage: boolean };
};

type ReleaseForm = {
    full: boolean;
    parts: Record<string, boolean>;
};

const groupIcons: Record<string, LucideIcon> = {
    'Core CRM': Building2,
    Support: LifeBuoy,
    'Revenue and operations': Wallet,
    Security: ShieldCheck,
};

const groupDescriptions: Record<string, string> = {
    'Core CRM':
        'The client list, the work raised against it, and the crews who do it.',
    Support:
        'The desk that answers a fault, the board a crew reads, and the reports that come back from site.',
    'Revenue and operations':
        'The pipeline before a job, the money around it, and the stock that makes it happen.',
    Security:
        'The one screen that holds a password. It is released like any other part, and on purpose.',
};

/**
 * Settings -> Release.
 *
 * The switchboard for a gradual handover. Each part of the system is either
 * live or absent: the navigation link is not rendered, the search does not
 * answer with its records, and its own addresses reply 404. Nothing is deleted
 * and no data is touched — switching a part back on puts it exactly where it
 * was.
 *
 * Full release is the day the handover ends. It switches every part on and
 * fixes the individual switches at on; the choices underneath are kept, so
 * turning it off restores the gradual state rather than flattening it.
 */
export default function ReleaseSettings({
    release,
    history,
    version,
}: ReleasePageProps) {
    // The form edits each part's own switch, not what Full release currently
    // makes visible. While the master switch is on, the boxes keep the gradual
    // arrangement underneath it, so turning it off restores that arrangement.
    const form = useForm<ReleaseForm>({
        full: release.full,
        parts: Object.fromEntries(
            Object.values(release.parts).map((part) => [
                part.key,
                part.chosen,
            ]),
        ),
    });

    const groups = Object.values(release.parts).reduce<
        Record<string, ReleasePart[]>
    >((carried, part) => {
        (carried[part.group] ??= []).push(part);

        return carried;
    }, {});

    const live = Object.values(form.data.parts).filter(Boolean).length;
    const total = Object.keys(form.data.parts).length;
    const hidden = total - live;
    const dirty =
        form.data.full !== release.full ||
        Object.values(release.parts).some(
            (part) => form.data.parts[part.key] !== part.chosen,
        );

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

    const togglePart = (key: string, checked: boolean) => {
        form.setData('parts', { ...form.data.parts, [key]: checked });
    };

    return (
        <>
            <Head title="Release" />

            <PageHeader
                title="Release"
                eyebrow={
                    <>
                        <Layers className="size-3.5" />
                        <span>Settings</span>
                    </>
                }
                description="What this installation shows, part by part. Release the system gradually, then switch on Full release when the handover is finished."
            />

            <Callout
                tone={form.data.full ? 'success' : 'info'}
                icon={form.data.full ? CheckCircle2 : Layers}
                title={
                    form.data.full
                        ? 'Full release is on — every part is visible'
                        : hidden === 0
                          ? 'Every part is visible'
                          : `${hidden} of ${total} parts are still hidden`
                }
            >
                {form.data.full
                    ? 'The individual switches below no longer decide anything. They keep their values, so turning Full release off puts the gradual arrangement back exactly as it was.'
                    : hidden === 0
                      ? 'The whole system is visible. Switch off anything that is not ready to be handed over; the staff side, the search and the dashboard follow immediately, with no deploy.'
                      : 'A hidden part is absent rather than greyed out: its sidebar link is not drawn, the top-bar search leaves its records out, the dashboard does not count them, and typing its address answers 404. Nothing is deleted and nobody is signed out.'}
            </Callout>

            <form
                className="flex flex-col gap-5"
                onSubmit={(event) => {
                    event.preventDefault();
                    submit();
                }}
            >
                <SectionCard
                    title="Full release"
                    description="The end of the gradual handover."
                    icon={GitBranch}
                    tone={form.data.full ? 'success' : 'slate'}
                >
                    <div className="flex items-start gap-3 rounded-lg bg-muted/40 p-3 ring-1 ring-inset ring-hairline">
                        <Checkbox
                            id="full"
                            className="mt-0.5"
                            checked={form.data.full}
                            onCheckedChange={(checked) =>
                                form.setData('full', checked === true)
                            }
                        />
                        <div className="min-w-0">
                            <Label htmlFor="full">
                                This is the full release
                            </Label>
                            <p className="mt-1 text-xs leading-relaxed text-muted-foreground">
                                Every part is shown, whatever the switches below
                                say. Turn it off again and the gradual
                                arrangement comes back unchanged — it is a
                                switch, not a one-way door.
                                {form.data.full ? (
                                    <>
                                        {' '}
                                        {live} of {total} parts are still chosen
                                        to stay visible underneath this.
                                    </>
                                ) : null}
                            </p>
                        </div>
                    </div>
                </SectionCard>

                {Object.entries(groups).map(([group, parts]) => {
                    const Icon = groupIcons[group] ?? Layers;

                    return (
                        <SectionCard
                            key={group}
                            title={group}
                            description={groupDescriptions[group]}
                            icon={Icon}
                            tone="solar"
                        >
                            <ul className="divide-hairline divide-y">
                                {parts.map((part) => {
                                    const checked =
                                        form.data.parts[part.key] ?? true;
                                    // What a person actually sees: the master
                                    // switch can be showing everything while a
                                    // part's own switch is off underneath it.
                                    const visible =
                                        form.data.full || checked;

                                    return (
                                        <li
                                            key={part.key}
                                            className="flex items-start gap-3 py-3 first:pt-0 last:pb-0"
                                        >
                                            <Checkbox
                                                id={`part-${part.key}`}
                                                className="mt-0.5"
                                                checked={checked}
                                                disabled={form.data.full}
                                                onCheckedChange={(value) =>
                                                    togglePart(
                                                        part.key,
                                                        value === true,
                                                    )
                                                }
                                            />
                                            <div className="min-w-0 flex-1">
                                                <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
                                                    <Label
                                                        htmlFor={`part-${part.key}`}
                                                        className={
                                                            form.data.full
                                                                ? 'text-muted-foreground'
                                                                : undefined
                                                        }
                                                    >
                                                        {part.label}
                                                    </Label>
                                                    <span
                                                        className={cn(
                                                            'rounded-full px-2 py-0.5 text-[10px] font-medium tracking-wide uppercase ring-1 ring-inset',
                                                            visible
                                                                ? 'bg-success-soft text-success ring-success/20'
                                                                : 'bg-muted text-muted-foreground ring-hairline',
                                                        )}
                                                    >
                                                        {visible
                                                            ? 'Visible'
                                                            : 'Hidden'}
                                                    </span>
                                                </div>
                                                <p className="mt-0.5 text-xs leading-relaxed text-muted-foreground">
                                                    {part.description}
                                                </p>
                                            </div>
                                        </li>
                                    );
                                })}
                            </ul>
                        </SectionCard>
                    );
                })}

                <FormActions
                    note={
                        dirty
                            ? form.data.full
                                ? 'Saving will show every part of the system.'
                                : 'Unsaved changes. Hidden parts keep their data.'
                            : 'Saved. What is on is what the staff sees.'
                    }
                >
                    <Button type="submit" disabled={form.processing || !dirty}>
                        {form.processing && <Spinner />}
                        Save release
                    </Button>
                </FormActions>
            </form>

            <SectionCard
                title="Version"
                description="The number this installation reports, and the newest entries behind it."
                icon={GitBranch}
                tone="slate"
            >
                <div className="flex flex-wrap items-baseline gap-x-3 gap-y-1">
                    <span className="crm-num font-mono text-2xl font-semibold">
                        {version.label}
                    </span>
                    <span className="text-xs text-muted-foreground">
                        from VERSION, written by{' '}
                        <span className="whitespace-nowrap font-mono">
                            php artisan crm:version
                        </span>
                    </span>
                </div>

                {version.recorded !== version.number ? (
                    <Callout
                        tone="warning"
                        className="mt-4"
                        title="The number and the release notes disagree"
                    >
                        VERSION says {version.number}, but the newest entry in
                        docs/releases.md is{' '}
                        {version.recorded ?? 'missing altogether'}. Run{' '}
                        <span className="font-mono">php artisan crm:version</span>{' '}
                        to see which file needs the correction.
                    </Callout>
                ) : null}

                {history.length === 0 ? (
                    <p className="mt-4 text-sm text-muted-foreground">
                        No release entries are recorded yet.
                    </p>
                ) : (
                    <ol className="mt-4 space-y-3">
                        {history.map((entry) => (
                            <li
                                key={`${entry.version}-${entry.date}`}
                                className="rounded-lg bg-muted/30 p-3 ring-1 ring-inset ring-hairline"
                            >
                                <div className="flex flex-wrap items-baseline justify-between gap-2">
                                    <span className="font-mono text-sm font-semibold">
                                        {entry.version}
                                    </span>
                                    <span className="text-[11px] text-muted-foreground">
                                        {entry.date}
                                    </span>
                                </div>
                                <p className="mt-1 line-clamp-4 text-xs leading-relaxed whitespace-pre-line text-muted-foreground">
                                    {entry.body}
                                </p>
                            </li>
                        ))}
                    </ol>
                )}
            </SectionCard>
        </>
    );
}
