// @design-system: layout/PublicChromeIsland
'use client';

/**
 * PublicChromeIsland — React island that renders SiteNav (mobile + desktop)
 * for public pages that use PublicAppShell instead of the full AppShell.
 *
 * Uses HydratedIsland for QueryClientProvider + LocaleProvider + ErrorBoundary.
 * Mobile bar: lg:hidden. Desktop bar: hidden lg:block.
 *
 * useAuthHint() drives reactive updates after hydration from the mh cookie.
 */

import { useCallback, useEffect, useState, type ReactNode } from 'react';
import { HydratedIsland } from '@/components/HydratedIsland';
import { SiteNav } from '@/components/ui/layout/SiteNav';
import { useAuthHint } from '@/lib/hooks/useAuthHint';
import { NotificationBell } from '@/components/ui/notification/NotificationBell';
import type { Locale } from '@/lib/i18n';
import { useT } from '@/lib/i18n/react';
import { AuthGateModal } from '@/features/auth-flow/AuthGateModal';
import { CheckoutModal } from '@/features/checkout-modal/CheckoutModal';
import { QueryProgress } from '@/components/ui/feedback/QueryProgress';
import { IconButton } from '@/components/ui/primitives/IconButton';
import { Icon } from '@/components/ui/icons/Icon';
import { CommandPalette } from '@/components/ui/overlays/CommandPalette';

export interface PublicChromeIslandProps {
  locale: Locale;
  currentPath?: string;
}

export type PublicChromeInnerProps = {
  currentPath?: string;
  /** Extra ReactNode prepended to mobile SiteNav end slot (before NotificationBell). */
  endExtra?: ReactNode;
  commandPaletteOpen?: boolean;
  onCommandPaletteOpenChange?: (open: boolean) => void;
  onCommandPaletteOpen?: () => void;
};

export function usePublicCommandPalette() {
  const [commandPaletteOpen, setCommandPaletteOpen] = useState(false);
  const openCommandPalette = useCallback(() => setCommandPaletteOpen(true), []);

  useEffect(() => {
    function onKeyDown(event: KeyboardEvent) {
      const key = event.key.toLowerCase();
      const isCommandK = (event.metaKey || event.ctrlKey) && key === 'k';
      const isSlash = event.key === '/' && !event.metaKey && !event.ctrlKey && !event.altKey;
      if (!isCommandK && !isSlash) return;
      if (isSlash && isTextEntryTarget(event.target)) return;
      event.preventDefault();
      setCommandPaletteOpen((current) => (isCommandK ? !current : true));
    }

    document.addEventListener('keydown', onKeyDown);
    return () => document.removeEventListener('keydown', onKeyDown);
  }, []);

  return {
    commandPaletteOpen,
    onCommandPaletteOpenChange: setCommandPaletteOpen,
    onCommandPaletteOpen: openCommandPalette,
  };
}

function isTextEntryTarget(target: EventTarget | null) {
  if (!(target instanceof HTMLElement)) return false;
  if (target.isContentEditable) return true;
  return target.closest('input, textarea, select, [contenteditable="true"]') !== null;
}

export function PublicChromeInner({
  currentPath = '/',
  endExtra,
  commandPaletteOpen = false,
  onCommandPaletteOpenChange = () => {},
  onCommandPaletteOpen = () => {},
}: PublicChromeInnerProps) {
  const auth = useAuthHint();
  const tCommon = useT('common');
  const inboxHref = currentPath.startsWith('/admin') ? '/admin/inbox' : undefined;

  const isGuest = !auth.loggedIn;
  const isAdmin = auth.isAdmin ?? false;
  const isVendor = auth.isVendor ?? false;
  const isAffiliate = auth.isAffiliate ?? false;
  const userName = auth.displayName;
  const phoneHint = auth.phoneHint;

  return (
    <>
      <QueryProgress />
      {/* `contents` keeps the wrapper out of the box tree so the sticky TopBar's parent
          box doesn't collapse to its own height (which kills `position: sticky`).
          `lg:hidden` still hides the subtree on desktop. */}
      <div className="contents lg:hidden">
        <SiteNav
          variant="mobile"
          currentPath={currentPath}
          isGuest={isGuest}
          isAdmin={isAdmin}
          isVendor={isVendor}
          isAffiliate={isAffiliate}
          userName={userName}
          phoneHint={phoneHint}
          endExtra={
            <>
              {endExtra}
              <NotificationBell inboxHref={inboxHref} />
            </>
          }
        />
      </div>
      <div className="hidden lg:contents">
        <SiteNav
          variant="desktop"
          currentPath={currentPath}
          isGuest={isGuest}
          isAdmin={isAdmin}
          isVendor={isVendor}
          isAffiliate={isAffiliate}
          userName={userName}
          phoneHint={phoneHint}
          desktopEndExtra={
            <IconButton
              variant="ghost"
              size="md"
              aria-label={tCommon('search')}
              data-testid="public-command-palette-trigger"
              onClick={onCommandPaletteOpen}
            >
              <Icon name="Search" size="md" />
            </IconButton>
          }
        />
      </div>
      <CommandPalette open={commandPaletteOpen} onOpenChange={onCommandPaletteOpenChange} />
      <AuthGateModal />
      <CheckoutModal />
    </>
  );
}

export function PublicChromeIsland({ locale, currentPath = '/' }: PublicChromeIslandProps) {
  const { commandPaletteOpen, onCommandPaletteOpenChange, onCommandPaletteOpen } =
    usePublicCommandPalette();

  useEffect(() => {
    (window as typeof window & { __PUBLIC_CHROME_READY?: boolean }).__PUBLIC_CHROME_READY = true;
    return () => {
      delete (window as typeof window & { __PUBLIC_CHROME_READY?: boolean }).__PUBLIC_CHROME_READY;
    };
  }, []);

  return (
    <HydratedIsland locale={locale}>
      <PublicChromeInner
        currentPath={currentPath}
        commandPaletteOpen={commandPaletteOpen}
        onCommandPaletteOpenChange={onCommandPaletteOpenChange}
        onCommandPaletteOpen={onCommandPaletteOpen}
      />
    </HydratedIsland>
  );
}
