/**
 * The application header: logo, where you are, search, Piggy.
 *
 * Search reads as a field because that is what people look for, but it is a
 * BUTTON, not an input. It was briefly a real `<input>` that opened the
 * palette on focus, and that is a keyboard trap: Tab moved into the field,
 * the modal took over, Escape left focus on `<body>`, and Tab from there ran
 * the same three elements and reopened the dialog — so no keyboard user could
 * ever reach the nav, the Piggy toggle or the page. A field that cannot be
 * focused without being replaced is not a field.
 *
 * The alternative — a real input filtering inline and escalating on Enter —
 * was rejected because the palette is the thing that answers, and an inline
 * filter would be a second search that ranks differently from the one ⌘K
 * opens. One search, one ranking; the control that opens it says so honestly.
 * (This is also what shadcn's own examples do.)
 *
 * Full width above both side panes rather than inset between them, so the
 * logo has somewhere to live and the panes have a fixed edge to hang from.
 */
import { useEffect, useState } from 'react';
import { Search } from 'lucide-react';
import { Link, useLocation } from 'react-router-dom';
import { useIdentity } from '@/lib/identity';
import { activeNavItem, visibleNav } from '@/lib/nav';
import { CommandPalette, searchLabel, searchPlaceholder } from './CommandPalette';
import { PiggyLogo } from './PiggyMark';
import { PiggyDockToggle } from './PiggyDock';
import { AudioControl } from './AudioControl';
import { Button, cn } from './ui';
import {
  Breadcrumb,
  BreadcrumbItem,
  BreadcrumbList,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from './ui/breadcrumb';
import { SidebarTrigger } from './ui/sidebar';

export function AppHeader() {
  const identity = useIdentity();
  const { pathname } = useLocation();
  const items = visibleNav(identity);
  const current = activeNavItem(items, pathname);

  const [commandOpen, setCommandOpen] = useState(false);
  // The button says what the palette will actually search, so the two cannot
  // disagree about whether this person's grants reach the book.
  const label = searchLabel(identity);
  const placeholder = searchPlaceholder(identity);

  useEffect(() => {
    const onKeyDown = (event: KeyboardEvent) => {
      if (event.key.toLowerCase() !== 'k' || (!event.metaKey && !event.ctrlKey)) return;
      event.preventDefault();
      setCommandOpen((open) => !open);
    };
    document.addEventListener('keydown', onKeyDown);
    return () => document.removeEventListener('keydown', onKeyDown);
  }, []);

  return (
    <header
      className={cn(
        'sticky top-0 z-40 flex w-full shrink-0 items-center gap-2 border-b border-border',
        // Translucent with a blur reads as native on iOS; the opaque fallback
        // keeps text legible where backdrop-filter is unsupported.
        'bg-surface/90 backdrop-blur-xl supports-[backdrop-filter]:bg-surface/75',
        'pr-[max(0.75rem,var(--safe-right))] lg:pr-[max(1rem,var(--safe-right))]',
        'pl-[max(0.5rem,var(--safe-left))] lg:pl-[max(0.75rem,var(--safe-left))]',
      )}
      style={{ height: 'var(--app-header-h)', paddingTop: 'var(--safe-top)' }}
    >
      <SidebarTrigger />

      <Link to="/" className="tap flex shrink-0 items-center rounded-lg px-1" aria-label="PIG home">
        <PiggyLogo />
      </Link>

      {current ? (
        <Breadcrumb className="ml-2 hidden min-w-0 lg:block">
          <BreadcrumbList className="flex-nowrap">
            <BreadcrumbItem className="text-muted">{current.group}</BreadcrumbItem>
            <BreadcrumbSeparator />
            <BreadcrumbItem className="min-w-0">
              <BreadcrumbPage className="truncate">{current.label}</BreadcrumbPage>
            </BreadcrumbItem>
          </BreadcrumbList>
        </Breadcrumb>
      ) : null}

      {/* min-w-0 on the search wrapper: without it the 393px header refuses to
          shrink below the field's intrinsic width and the page scrolls. */}
      <div className="ml-auto flex min-w-0 items-center gap-1">
        <button
          type="button"
          aria-haspopup="dialog"
          aria-expanded={commandOpen}
          className={cn(
            // A control, so 12px radius and the 44px floor the rest of the
            // product holds — it reads as a field but it is a button, and a
            // button that is 36px tall is one this system does not have.
            'hidden h-11 min-w-0 items-center gap-2 rounded-lg border border-border bg-surface-2 px-3',
            'text-left text-sm text-muted transition-colors duration-1 ease-enter hover:text-fg md:flex md:w-56 lg:w-72',
          )}
          onClick={() => setCommandOpen(true)}
        >
          <Search className="size-4 shrink-0" aria-hidden />
          <span className="min-w-0 flex-1 truncate">{label}…</span>
          <kbd className="shrink-0 rounded-md border border-border px-1.5 py-0.5 font-mono text-xs">
            ⌘K
          </kbd>
        </button>

        <Button
          type="button"
          variant="ghost"
          size="icon"
          className="text-muted md:hidden"
          aria-label={placeholder}
          onClick={() => setCommandOpen(true)}
        >
          <Search className="size-5" aria-hidden />
        </Button>

        <AudioControl className="hidden sm:flex" />
        <PiggyDockToggle />
      </div>

      <CommandPalette destinations={items} open={commandOpen} onOpenChange={setCommandOpen} />
    </header>
  );
}
