"use client";

import { useMutation, useQueryClient } from "@tanstack/react-query";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useEffect, useRef, useState } from "react";
import { api } from "@/lib/api";
import { useSession } from "@/lib/session";
import { useTheme, type ThemePref } from "@/lib/theme";

const APPEARANCE: { value: ThemePref; label: string }[] = [
    { value: "light", label: "Light" },
    { value: "dark", label: "Dark" },
    { value: "system", label: "System" },
];

/*
 * Everything here is about YOU rather than about the account: your settings,
 * your password, how you want the app to look, and leaving. None of it is a
 * destination worth a slot in the primary nav, which is why Settings moved off
 * the bar and into this menu.
 */
export function AccountMenu({ staff = false }: { staff?: boolean }) {
    const { session } = useSession();
    const [open, setOpen] = useState(false);
    const [pref, setPref] = useTheme();
    const wrap = useRef<HTMLDivElement>(null);
    const router = useRouter();
    const qc = useQueryClient();

    useEffect(() => {
        if (!open) return;
        const onDown = (e: MouseEvent) => {
            if (wrap.current && !wrap.current.contains(e.target as Node)) setOpen(false);
        };
        const onKey = (e: KeyboardEvent) => {
            if (e.key === "Escape") setOpen(false);
        };
        document.addEventListener("mousedown", onDown);
        document.addEventListener("keydown", onKey);
        return () => {
            document.removeEventListener("mousedown", onDown);
            document.removeEventListener("keydown", onKey);
        };
    }, [open]);

    const signOut = useMutation({
        mutationFn: api.logout,
        // Clear the cache before leaving: a cached account response outliving
        // the session would show the next person who signs in on this browser
        // the previous account's name for a beat.
        onSettled: () => {
            qc.clear();
            router.replace("/login");
        },
    });

    const email = session?.email ?? "";
    const initials =
        email
            .split("@")[0]
            .split(/[.\-_]/)
            .slice(0, 2)
            .map((p) => p[0]?.toUpperCase() ?? "")
            .join("") || "?";

    return (
        <div className="relative" ref={wrap}>
            <button
                type="button"
                onClick={() => setOpen((v) => !v)}
                aria-expanded={open}
                aria-haspopup="menu"
                className={`flex items-center gap-2 rounded-sm border px-2 py-1 text-[0.8rem] ${
                    open ? "border-accent text-ink" : "border-rule text-ink-2"
                } bg-panel hover:border-ink-3`}
            >
                <span className="grid h-[18px] w-[18px] shrink-0 place-items-center rounded-full bg-accent font-mono text-[0.56rem] font-bold text-accent-ink">
                    {initials}
                </span>
                <span className="hidden max-w-[16ch] truncate sm:inline">{email}</span>
                <span aria-hidden className="text-[0.6rem] text-ink-3">
                    ▾
                </span>
            </button>

            {open && (
                <div
                    role="menu"
                    // --shadow rather than a literal: globals.css defines it per
                    // theme, and a hardcoded rgba would be a colour value living
                    // in a component, which this app's tokens rule forbids.
                    className="absolute right-0 top-[calc(100%+8px)] z-50 grid w-64 overflow-hidden rounded border border-rule bg-panel shadow-[var(--shadow)]"
                >
                    <div className="grid gap-0.5 border-b border-rule-soft px-3 py-2.5">
                        <strong className="truncate text-[0.86rem]">{email}</strong>
                        <span className="font-mono text-[0.66rem] uppercase tracking-[0.1em] text-ink-3">
                            {staff ? "Vantage staff" : (session?.account_role ?? "member")}
                        </span>
                    </div>

                    {!staff && (
                        <Link
                            href="/settings"
                            role="menuitem"
                            onClick={() => setOpen(false)}
                            className="px-3 py-2 text-[0.86rem] text-ink hover:bg-accent-wash"
                        >
                            Settings
                        </Link>
                    )}

                    <div className="grid gap-1.5 border-y border-rule-soft px-3 py-2.5">
                        <span className="font-mono text-[0.66rem] uppercase tracking-[0.12em] text-ink-3">
                            Appearance
                        </span>
                        <div className="flex overflow-hidden rounded-sm border border-rule">
                            {APPEARANCE.map((a) => (
                                <button
                                    key={a.value}
                                    type="button"
                                    onClick={() => setPref(a.value)}
                                    aria-pressed={pref === a.value}
                                    className={`flex-1 px-0 py-1 font-mono text-[0.62rem] uppercase tracking-[0.08em] ${
                                        pref === a.value
                                            ? "bg-accent text-accent-ink"
                                            : "bg-panel text-ink-3 hover:text-ink-2"
                                    }`}
                                >
                                    {a.label}
                                </button>
                            ))}
                        </div>
                    </div>

                    <button
                        type="button"
                        role="menuitem"
                        onClick={() => signOut.mutate()}
                        disabled={signOut.isPending}
                        className="px-3 py-2 text-left text-[0.86rem] text-expired hover:bg-accent-wash"
                    >
                        {signOut.isPending ? "Signing out…" : "Sign out"}
                    </button>
                </div>
            )}
        </div>
    );
}
