"use client";

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useParams } from "next/navigation";
import { useState } from "react";
import Link from "next/link";
import clsx from "clsx";
import { api, type Deployment, type InjectionState } from "@/lib/api";
import { Ledger } from "@/components/Ledger";
import { PageHeader } from "@/components/PageHeader";
import PlanConfigurator, { type PlanChoice } from "@/components/PlanConfigurator";
import { IssuePanel } from "./IssuePanel";

const INJECTION: Record<InjectionState, { label: string; tone: string }> = {
    current: { label: "Control plane holds the current licence", tone: "text-valid" },
    stale: {
        label: "Control plane holds an older blob the reconciler will repair it",
        tone: "text-warn",
    },
    missing: { label: "No matching instance in the control plane", tone: "text-expired" },
    none_issued: { label: "Nothing issued yet, so nothing to inject", tone: "text-ink-3" },
};

export default function StaffInstancePage() {
    const id = String(useParams().id);
    const { data, isLoading } = useQuery({
        queryKey: ["staff-instance", id],
        queryFn: () => api.staff.instance(id),
        refetchInterval: 30_000,
    });

    if (isLoading || !data) return <p className="text-ink-3">Loading…</p>;

    const inj = data.injection.state ? INJECTION[data.injection.state] : undefined;

    return (
        <div className="grid gap-8">
            <div className="grid gap-3">
                <PageHeader
                    back={{
                        href: `/staff/accounts/${data.account.account_id}`,
                        label: data.account.name || "Account",
                    }}
                    title={data.instance.name || data.instance.instance_id}
                    subtitle={
                        <>
                            <Link href={`/staff/accounts/${data.account.account_id}`} className="text-accent underline">
                                {data.account.name || data.account.account_id}
                            </Link>
                            <span className="text-ink-3">
                                {" "}
                                · {data.instance.deployment} · {data.instance.status}
                                {data.instance.relink_count > 0 && ` · ${data.instance.relink_count} relinks this term`}
                            </span>
                        </>
                    }
                    record={[{ key: "Instance", value: data.instance.instance_id, copy: true }, ...(data.instance.slug ? [{ key: "Slug", value: data.instance.slug }] : [])]}
                />
                {data.injection.applicable && inj && <p className={clsx("font-mono text-[0.72rem]", inj.tone)}>{inj.label}</p>}
            </div>

            <section className="grid gap-3 rounded border border-rule bg-panel p-5">
                <h2 className="text-xl">Licence history</h2>
                <Ledger licenses={data.licenses} />
                <IssuePanel instanceId={data.instance.instance_id} />
            </section>

            <EntitlementSection instanceId={data.instance.instance_id} deployment={data.instance.deployment} />
        </div>
    );
}

function EntitlementSection({ instanceId, deployment }: { instanceId: string; deployment: Deployment }) {
    const qc = useQueryClient();
    const { data: plans = [] } = useQuery({
        queryKey: ["staff", "plans"],
        queryFn: api.staff.plans,
    });
    const { data: catalogue = [] } = useQuery({
        queryKey: ["staff", "catalogue"],
        queryFn: api.staff.catalogue,
    });
    const { data } = useQuery({
        queryKey: ["staff", "entitlement", instanceId],
        queryFn: () => api.staff.entitlement(instanceId),
        retry: false,
    });

    const ent = data?.entitlement;
    const [draft, setDraft] = useState<PlanChoice | null>(null);
    const choice: PlanChoice =
        draft ??
        (ent
            ? {
                  tier: ent.tier,
                  term: ent.term,
                  servers: ent.desired.servers,
                  features: ent.desired.features ?? [],
              }
            : { tier: "professional", term: deployment === "self_hosted" ? "annual" : "monthly", servers: 3, features: [] });

    const save = useMutation({
        mutationFn: (grant: boolean) => api.staff.setEntitlement(instanceId, { ...choice, grant }),
        onSuccess: () => {
            setDraft(null);
            qc.invalidateQueries({ queryKey: ["staff", "entitlement", instanceId] });
        },
    });

    return (
        <section className="rounded-lg border border-rule bg-panel p-4">
            <header className="mb-3">
                <h2 className="text-[0.95rem] font-medium text-ink">Entitlement</h2>
                <p className="text-[0.78rem] text-ink-3">
                    What this instance is allowed. A licence is signed from <em>granted</em>, never from <em>desired</em>.
                </p>
            </header>

            {ent && data?.pending && (
                <p className="mb-3 rounded border border-warn/50 bg-panel-2 px-2.5 py-2 text-[0.82rem] text-ink-2">
                    Pending change currently granted {ent.granted.servers} servers, configured for {ent.desired.servers}
                    {ent.scheduled_change_at ? `, effective ${new Date(ent.scheduled_change_at).toLocaleDateString("en-GB", { day: "numeric", month: "long", year: "numeric" })}` : ""}.
                </p>
            )}

            <PlanConfigurator deployment={deployment} value={choice} plans={plans} catalogue={catalogue} onChange={setDraft} disabled={save.isPending} />

            <div className="mt-4 flex flex-wrap gap-2">
                <button type="button" disabled={save.isPending} onClick={() => save.mutate(false)} className="rounded border border-rule px-3 py-1.5 text-[0.85rem] text-ink-2 disabled:opacity-40">
                    Save as configured
                </button>
                <button
                    type="button"
                    disabled={save.isPending}
                    onClick={() => save.mutate(true)}
                    className="rounded border border-accent/50 px-3 py-1.5 text-[0.85rem] text-accent disabled:opacity-40"
                >
                    Save and grant
                </button>
            </div>
            <p className="mt-2 text-[0.72rem] text-ink-3">Granting takes effect on the next licence issued. It does not issue one.</p>
            {save.error && <p className="mt-2 text-[0.82rem] text-expired">{String((save.error as Error).message)}</p>}
        </section>
    );
}
