"use client";

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useState } from "react";
import { API_BASE, ApiError, NotConnected, api, type AccountRole } from "@/lib/api";
import { useSession } from "@/lib/session";
import { NotConnectedPanel } from "@/components/NotConnected";
import { Button } from "@/components/Button";
import { Field } from "@/components/Field";
import { PageFrame, RailCard } from "@/components/PageFrame";
import { formatDate } from "@/lib/format";

const ROLES: AccountRole[] = ["owner", "admin", "member"];

const WHAT_ROLES_DO: [AccountRole, string][] = [
    ["owner", "Everything, including billing."],
    ["admin", "Invite people, create instances, grant access. No billing."],
    ["member", "Sign in to the instances they are given."],
];

export function InvitePanel() {
    const qc = useQueryClient();
    const { session } = useSession();
    const [email, setEmail] = useState("");
    const [role, setRole] = useState<AccountRole>("member");
    const [error, setError] = useState<string | null>(null);

    const users = useQuery({ queryKey: ["account-users"], queryFn: api.accountUsers });
    const refresh = () => qc.invalidateQueries({ queryKey: ["account-users"] });
    const fail = (e: unknown) =>
        setError(e instanceof ApiError ? e.message : "Something went wrong. Try again.");

    const invite = useMutation({
        mutationFn: () => api.invite(email.trim().toLowerCase(), role),
        onSuccess: () => {
            setEmail("");
            setRole("member");
            refresh();
        },
        onError: fail,
    });
    const setRoleFor = useMutation({
        mutationFn: (v: { id: string; role: AccountRole }) => api.setAccountRole(v.id, v.role),
        onSuccess: refresh,
        onError: fail,
    });
    const remove = useMutation({
        mutationFn: (id: string) => api.removeAccountUser(id),
        onSuccess: refresh,
        onError: fail,
    });

    if (users.error instanceof NotConnected) return <NotConnectedPanel url={API_BASE} />;

    const myRole = session?.account_role;
    const canManage = myRole === "owner" || myRole === "admin";
    const assignable = myRole === "owner" ? ROLES : ROLES.filter((r) => r !== "owner");

    return (
        <PageFrame
            aside={
                <>
                    {canManage && (
                        <RailCard title="Invite someone">
                            <form
                                className="grid gap-3"
                                onSubmit={(e) => {
                                    e.preventDefault();
                                    setError(null);
                                    if (email.trim()) invite.mutate();
                                }}
                            >
                                <Field
                                    label="Email"
                                    type="email"
                                    value={email}
                                    onChange={(e) => setEmail(e.target.value)}
                                    required
                                    hint="They choose their own password from the emailed link. Nothing happens until they open it."
                                />
                                <label className="grid gap-1.5">
                                    <span className="font-mono text-[0.72rem] uppercase tracking-[0.1em] text-ink-3">
                                        Account role
                                    </span>
                                    <select
                                        value={role}
                                        onChange={(e) => setRole(e.target.value as AccountRole)}
                                        className="rounded border border-rule bg-panel-2 px-2.5 py-2 font-mono text-ink"
                                    >
                                        {assignable.map((r) => (
                                            <option key={r} value={r}>
                                                {r}
                                            </option>
                                        ))}
                                    </select>
                                </label>
                                <Button type="submit" disabled={invite.isPending || !email.trim()}>
                                    {invite.isPending ? "Sending…" : "Send invitation"}
                                </Button>
                            </form>
                        </RailCard>
                    )}

                    <RailCard title="What the roles do">
                        <dl className="grid gap-2">
                            {WHAT_ROLES_DO.map(([r, what]) => (
                                <div key={r} className="grid gap-0.5">
                                    <dt className="font-mono text-[0.68rem] uppercase tracking-[0.08em] text-ink">
                                        {r}
                                    </dt>
                                    <dd className="m-0 text-[0.8rem] text-ink-2">{what}</dd>
                                </div>
                            ))}
                        </dl>
                        <p className="border-t border-rule-soft pt-2 text-[0.8rem] text-ink-2">
                            An account role is not access to an instance. Give someone that on the
                            instance itself.
                        </p>
                    </RailCard>
                </>
            }
        >
            {error && (
                <p className="rounded border border-expired bg-panel p-3 text-[0.9rem] text-expired">
                    {error}
                </p>
            )}

            <div className="overflow-x-auto rounded border border-rule bg-panel">
                <table className="w-full border-collapse text-left text-[0.9rem]">
                    <thead>
                        <tr className="border-b border-rule bg-panel-2 font-mono text-[0.68rem] uppercase tracking-[0.1em] text-ink-3">
                            <th className="px-4 py-2.5 font-normal">Email</th>
                            <th className="px-4 py-2.5 font-normal">Account role</th>
                            <th className="px-4 py-2.5 font-normal">Status</th>
                            <th className="px-4 py-2.5" />
                        </tr>
                    </thead>
                    <tbody>
                        {(users.data ?? []).map((u) => {
                            const isSelf = u.email === session?.email;
                            return (
                                <tr key={u.user_id} className="border-b border-rule-soft last:border-0">
                                    <td className="px-4 py-3">
                                        {u.email}
                                        {isSelf && <span className="ml-2 text-ink-3">(you)</span>}
                                    </td>
                                    <td className="px-4 py-3">
                                        {canManage && !isSelf ? (
                                            <select
                                                value={u.account_role}
                                                onChange={(e) =>
                                                    setRoleFor.mutate({
                                                        id: u.user_id,
                                                        role: e.target.value as AccountRole,
                                                    })
                                                }
                                                className="rounded border border-rule bg-panel-2 px-2 py-1 font-mono text-[0.82rem] text-ink"
                                            >
                                                {assignable.map((r) => (
                                                    <option key={r} value={r}>
                                                        {r}
                                                    </option>
                                                ))}
                                            </select>
                                        ) : (
                                            <span className="font-mono text-[0.82rem]">
                                                {u.account_role}
                                            </span>
                                        )}
                                    </td>
                                    <td className="px-4 py-3 text-ink-2">
                                        {u.verified_at
                                            ? `Active since ${formatDate(u.verified_at)}`
                                            : "Invitation pending"}
                                    </td>
                                    <td className="px-4 py-3 text-right">
                                        {canManage && !isSelf && (
                                            <button
                                                type="button"
                                                className="text-[0.82rem] font-semibold text-expired underline"
                                                onClick={() => {
                                                    if (
                                                        confirm(
                                                            `Remove ${u.email}? They lose access to every instance on this account.`,
                                                        )
                                                    )
                                                        remove.mutate(u.user_id);
                                                }}
                                            >
                                                Remove
                                            </button>
                                        )}
                                    </td>
                                </tr>
                            );
                        })}
                        {users.data?.length === 0 && (
                            <tr>
                                <td colSpan={4} className="px-4 py-6 text-ink-3">
                                    Nobody yet.
                                </td>
                            </tr>
                        )}
                    </tbody>
                </table>
            </div>
        </PageFrame>
    );
}
