'use client';

import { useState } from 'react';
import { ChevronDown, LogOut, UserRound } from 'lucide-react';
import { Button, cn } from '@i-learned/ui';

/**
 * Account menu and sign-out.
 *
 * Sign-out is a POST rather than a link: a GET that mutates state can be
 * triggered by a prefetch or an image tag, which would log people out
 * unexpectedly.
 */
export function UserMenu({
  displayName,
  email,
  roles,
}: {
  displayName: string;
  email: string;
  roles: readonly string[];
}): React.JSX.Element {
  const [open, setOpen] = useState(false);
  const [signingOut, setSigningOut] = useState(false);

  async function signOut(): Promise<void> {
    setSigningOut(true);
    try {
      await fetch('/api/v1/auth/logout', { method: 'POST' });
    } finally {
      window.location.assign('/login');
    }
  }

  const initials = displayName
    .split(' ')
    .filter(Boolean)
    .slice(0, 2)
    .map((part) => part.charAt(0).toUpperCase())
    .join('');

  return (
    <div className="relative">
      <button
        type="button"
        onClick={() => setOpen((value) => !value)}
        aria-expanded={open}
        aria-haspopup="menu"
        className="flex items-center gap-2 rounded-[var(--radius-control)] px-2 py-1.5 text-sm transition-colors hover:bg-surface-sunken"
      >
        <span
          className="flex size-7 items-center justify-center rounded-full bg-brand-600 text-xs font-semibold text-white"
          aria-hidden="true"
        >
          {initials}
        </span>
        <span className="hidden max-w-36 truncate text-ink sm:block">{displayName}</span>
        <ChevronDown className="size-4 text-ink-subtle" aria-hidden="true" />
      </button>

      {open ? (
        <>
          <button
            type="button"
            className="fixed inset-0 z-10 cursor-default"
            aria-hidden="true"
            tabIndex={-1}
            onClick={() => setOpen(false)}
          />
          <div
            role="menu"
            className={cn(
              'absolute right-0 z-20 mt-1 w-64 rounded-[var(--radius-card)] border border-border',
              'bg-surface p-1.5 shadow-[var(--shadow-overlay)]',
            )}
          >
            <div className="border-b border-border px-2.5 pb-2.5 pt-1.5">
              <p className="truncate text-sm font-medium text-ink">{displayName}</p>
              <p className="truncate text-xs text-ink-subtle">{email}</p>
              {roles.length > 0 ? (
                <p className="mt-1.5 flex flex-wrap gap-1">
                  {roles.map((role) => (
                    <span
                      key={role}
                      className="rounded-full bg-surface-sunken px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-ink-muted"
                    >
                      {role.toLowerCase()}
                    </span>
                  ))}
                </p>
              ) : null}
            </div>

            <div className="pt-1.5">
              <a
                href="/account"
                role="menuitem"
                className="flex items-center gap-2 rounded-[var(--radius-control)] px-2.5 py-2 text-sm text-ink-muted hover:bg-surface-sunken hover:text-ink"
              >
                <UserRound className="size-4" aria-hidden="true" />
                Account settings
              </a>

              <Button
                variant="ghost"
                role="menuitem"
                onClick={signOut}
                loading={signingOut}
                className="w-full justify-start px-2.5 text-danger hover:bg-danger-bg hover:text-danger"
              >
                <LogOut className="size-4" aria-hidden="true" />
                Sign out
              </Button>
            </div>
          </div>
        </>
      ) : null}
    </div>
  );
}
