"use client";

import Link from "next/link";
import clsx from "clsx";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useEffect, useState } from "react";
import { api, type Instance, type License } from "@/lib/api";
import { daysRemaining, formatDate, licenceState, limitLabel } from "@/lib/format";
import { StatePill } from "./StatePill";
import { Button, LinkButton } from "./Button";

const STRIPE = {
    valid: "before:bg-valid",
    warn: "before:bg-warn",
    expired: "before:bg-expired",
    none: "before:bg-accent",
} as const;

const KEY = (id: string) => `vantage-hq-record-open:${id}`;

/*
 * One instance, open or closed.
 *
 * Closed it is a row name, tier, host, term bar, state. Open it adds what the
 * licence includes, who can sign in, and the actions. Deliberately ONE component
 * rather than a card and a detail panel: two components meant a single-instance
 * account got a third of a row of summary with its substance a click away, and
 * a six-instance account got a grid of summaries with no way to look closer.
 *
 * It defaults open when it is the only instance or when it needs attention,
 * because the thing that needs you is the thing that should be open. A manual
 * toggle is remembered per instance and beats the default from then on.
 */
export function InstanceRecord({ instance, license, reapAfterDays, defaultOpen = false }: { instance: Instance; license?: License; reapAfterDays?: number; defaultOpen?: boolean }) {
    const state = licenceState(license?.expires_at, Boolean(license));
    const days = license ? daysRemaining(license.expires_at) : 0;
    const cloud = instance.deployment === "cloud";
    const termDays = instance.tier === "free" ? 30 : 365;
    const deleteInDays = license && reapAfterDays ? daysRemaining(license.expires_at) + reapAfterDays : null;

    const [open, setOpen] = useState(defaultOpen);
    useEffect(() => {
        const saved = localStorage.getItem(KEY(instance.instance_id));
        if (saved !== null) setOpen(saved === "1");
    }, [instance.instance_id]);

    const toggle = () => {
        setOpen((v) => {
            localStorage.setItem(KEY(instance.instance_id), v ? "0" : "1");
            return !v;
        });
    };

    const qc = useQueryClient();
    const renew = useMutation({
        mutationFn: () => api.renewInstance(instance.instance_id),
        onSuccess: () => qc.invalidateQueries({ queryKey: ["account"] }),
    });
    const canRenew = instance.tier === "free" && license !== undefined && days <= 7;

    // Only fetched once the record is open, and only for cloud: a self-hosted
    // install manages its own users and the endpoint refuses it.
    const members = useQuery({
        queryKey: ["members", instance.instance_id],
        queryFn: () => api.members(instance.instance_id),
        enabled: open && cloud,
    });

    const panelId = `record-${instance.instance_id}`;

    return (
        <article className={clsx("relative grid gap-3.5 rounded border border-rule bg-panel p-4 pl-5", "before:absolute before:inset-y-0 before:left-0 before:w-1 before:content-['']", STRIPE[state])}>
            <div className="flex flex-wrap items-start justify-between gap-3">
                <div className="min-w-0">
                    <h2 className="text-[1.22rem]">{instance.name || "Unnamed instance"}</h2>
                    <p className="mt-1 font-mono text-[0.68rem] uppercase tracking-[0.1em] text-ink-3">
                        {cloud ? "Cloud" : "Self-hosted"}
                        {instance.tier ? ` · ${instance.tier.replace("_", " ")}` : ""}
                        {` · created ${formatDate(instance.created_at)}`}
                    </p>
                    {cloud && instance.slug && (
                        <a href={`https://${instance.slug}.vantage.hostxtra.co.uk`} className="mt-1.5 inline-block font-mono text-[0.78rem] text-accent underline">
                            {instance.slug}.vantage.hostxtra.co.uk &rarr;
                        </a>
                    )}
                </div>

                <div className="flex shrink-0 items-center gap-2.5">
                    <StatePill state={state} />
                    <button
                        type="button"
                        onClick={toggle}
                        aria-expanded={open}
                        aria-controls={panelId}
                        aria-label={open ? "Hide details" : "Show details"}
                        className="grid h-[26px] w-[26px] place-items-center rounded-sm border border-rule bg-panel text-[0.6rem] text-ink-3 hover:border-accent hover:text-accent"
                    >
                        <span aria-hidden className={clsx("block transition-transform", open && "rotate-180")}>
                            ▲
                        </span>
                    </button>
                </div>
            </div>

            {license && state !== "expired" && (
                <div className="grid max-w-md gap-1.5">
                    <div className="flex justify-between font-mono text-[0.78rem] tabular-nums text-ink-2">
                        <span>{days} days remaining</span>
                        <span>Renews {formatDate(license.expires_at)}</span>
                    </div>
                    <div className="h-1 overflow-hidden rounded-sm bg-rule-soft">
                        <div
                            className={clsx("h-full", state === "warn" ? "bg-warn" : "bg-valid")}
                            style={{
                                width: `${Math.max(2, Math.min(100, (days / termDays) * 100))}%`,
                            }}
                        />
                    </div>
                </div>
            )}

            {state === "expired" && (
                <div className="grid gap-1">
                    <p className="text-[0.82rem] text-ink-2">Servers and monitors are still running, and your agents keep their keys. Changes are disabled until you renew.</p>
                    {deleteInDays !== null && (
                        <p className="text-[0.82rem] font-semibold text-expired">
                            {deleteInDays <= 0 ? "Scheduled for deletion." : `Deleted in ${deleteInDays} ${deleteInDays === 1 ? "day" : "days"} unless renewed.`}
                        </p>
                    )}
                </div>
            )}

            {state === "none" && <p className="text-[0.82rem] text-ink-2">You have paid for this but it is not attached to an install yet, so no licence has been issued. Linking takes a minute.</p>}

            <div id={panelId} className={clsx("gap-3.5", open ? "grid" : "hidden")}>
                {license && (
                    <div className="grid gap-2 border-t border-rule-soft pt-3">
                        <p className="font-mono text-[0.68rem] uppercase tracking-[0.12em] text-ink-3">Included in {instance.tier?.replace("_", " ") ?? "this licence"}</p>
                        <div className="flex flex-wrap gap-x-7 gap-y-2.5">
                            <Stat n={limitLabel(license.limits.max_servers)} label="Servers" />
                            <Stat n={limitLabel(license.limits.max_secret_groups)} label="Secret groups" />
                            <Stat n={limitLabel(license.limits.max_channels)} label="Channels" />
                            <Stat n={license.features.length ? license.features.join(" · ") : "None"} label="Features" quiet={license.features.length === 0} />
                        </div>
                    </div>
                )}

                {cloud && (
                    <div className="grid gap-2 border-t border-rule-soft pt-3">
                        <p className="font-mono text-[0.68rem] uppercase tracking-[0.12em] text-ink-3">Who can sign in</p>
                        <div className="flex flex-wrap items-center gap-2">
                            {(members.data ?? []).map((m) => (
                                <span key={m.member_id} className="inline-flex items-center gap-1.5 rounded-full border border-rule-soft py-0.5 pl-0.5 pr-2.5 text-[0.78rem] text-ink-2">
                                    <span className="grid h-[18px] w-[18px] place-items-center rounded-full bg-accent font-mono text-[0.56rem] font-bold text-accent-ink">
                                        {m.email.slice(0, 2).toUpperCase()}
                                    </span>
                                    {m.email}
                                </span>
                            ))}
                            {members.isLoading && <span className="text-[0.82rem] text-ink-3">Loading…</span>}
                            {members.data?.length === 0 && <span className="text-[0.82rem] text-ink-3">Nobody yet.</span>}
                            <Link href={`/instances/${instance.instance_id}`} className="text-[0.82rem] font-semibold text-accent underline">
                                Manage access
                            </Link>
                        </div>
                    </div>
                )}

                <div className="flex flex-wrap items-center gap-2.5">
                    {state === "none" ? (
                        // A paid placeholder (awaiting_link) claims its real install
                        // UUID in place. Anything else without a licence gets one from
                        // the purchase page (self-hosted Free is created there).
                        instance.status === "awaiting_link" ? (
                            <LinkButton href={`/instances/link?claim=${instance.instance_id}`}>Link an install</LinkButton>
                        ) : (
                            <LinkButton href="/purchase">Get a licence</LinkButton>
                        )
                    ) : cloud && instance.slug ? (
                        <>
                            <LinkButton external href={`https://${instance.slug}.vantage.hostxtra.co.uk`}>
                                Open Cloud Instance
                            </LinkButton>
                            <LinkButton variant="line" href={`/instances/${instance.instance_id}`}>
                                View Instance Settings
                            </LinkButton>
                        </>
                    ) : (
                        <LinkButton href={`/instances/${instance.instance_id}`}>View Instance Settings</LinkButton>
                    )}

                    {canRenew && (
                        <Button type="button" variant="line" onClick={() => renew.mutate()} disabled={renew.isPending}>
                            {renew.isPending ? "Renewing…" : "Renew"}
                        </Button>
                    )}
                </div>
            </div>
        </article>
    );
}

function Stat({ n, label, quiet }: { n: string; label: string; quiet?: boolean }) {
    return (
        <div className="grid gap-px">
            <b className={clsx("tabular-nums tracking-[-0.02em]", quiet ? "text-[0.95rem] font-semibold text-ink-3" : "text-[1.18rem] font-extrabold")}>{n}</b>
            <span className="font-mono text-[0.64rem] uppercase tracking-[0.1em] text-ink-3">{label}</span>
        </div>
    );
}
