// <SettingsMenu> — a single header icon-button + popover holding the
// client-local overrides a page has (theme, reduced motion). Originated
// in swarm-ui, duplicated to the agent terminal page (mara: "agent
// terminal page should get the settings panel from swarm ui as well"),
// then unified here per her review on that PR: "i think the component
// should be shared. motion setting is missing." — one component, both
// pages import it, motion included unconditionally rather than
// agent-only.
//
// Trigger is `Badge` (`../badge/Badge.js`) with `../icons.js`'s
// `GearIcon` — an inline SVG, not a text/emoji glyph (see that file's
// comment for why a glyph is the wrong tool for a trigger's own icon;
// this file went through one regression on exactly that, caught by
// mara: "settings icon looks weird since component extract").
// `variant="quiet"` drops `Badge`'s default filled-pill look, which is
// right for a status/picker chip but wrong for this icon-only header
// button (mara again: "link and settings button should not have the
// badge bg") — see `Badge.tsx`'s `BadgeVariant` comment.
//
// Storage keys are the caller's responsibility (`themeKey`/`motionKey`
// props), not derived here — a page mounts `useApplyThemeOverride`/
// `useApplyMotionOverride` (`./theme-apply.js`/`./motion-apply.js`)
// once, high in its tree, with the SAME key strings passed to this
// component, so the two stay in sync without this component owning any
// page-specific naming decision.
import { useEffect, useRef, useState } from "preact/hooks";
import type { ComponentChildren } from "preact";
import { Badge } from "../badge/Badge.js";
import { GearIcon } from "../icons.js";
import { useThemeOverride, type ThemeOverride } from "./theme-apply.js";
import { useMotionOverride, type MotionOverride } from "./motion-apply.js";
import "./SettingsMenu.css";

const THEME_OPTIONS: ThemeOverride[] = ["system", "light", "dark"];
const MOTION_OPTIONS: MotionOverride[] = ["system", "allow", "reduce"];

export interface SettingsMenuProps {
  themeKey: string;
  motionKey: string;
  /**
   * Consumer-owned extra row(s), rendered inside the popover after the
   * built-in theme/motion rows. Not a named boolean prop per setting —
   * a `showExpandDetails?: boolean` attempt drew mara's review: "you
   * cannot just add it like this - if we have more and more options
   * there in different places we will keep accumulating cruft in the
   * shared component." A caller owns its row(s) entirely (state,
   * storage key, markup); this component never learns they exist. Use
   * `settings-menu-row` (this file's CSS) on each row's outer element
   * to match spacing/typography — see `Root.tsx` for a worked example.
   */
  children?: ComponentChildren;
}

export function SettingsMenu({
  themeKey,
  motionKey,
  children,
}: SettingsMenuProps) {
  const [open, setOpen] = useState(false);
  const rootRef = useRef<HTMLDivElement>(null);
  const [theme, setTheme] = useThemeOverride(themeKey);
  const [motion, setMotion] = useMotionOverride(motionKey);

  // Close on an outside click or Escape — only listens while open.
  useEffect(() => {
    if (!open) return;
    function onPointerDown(e: PointerEvent) {
      if (
        rootRef.current &&
        e.target instanceof Node &&
        !rootRef.current.contains(e.target)
      )
        setOpen(false);
    }
    function onKeyDown(e: KeyboardEvent) {
      if (e.key === "Escape") setOpen(false);
    }
    document.addEventListener("pointerdown", onPointerDown, true);
    document.addEventListener("keydown", onKeyDown);
    return () => {
      document.removeEventListener("pointerdown", onPointerDown, true);
      document.removeEventListener("keydown", onKeyDown);
    };
  }, [open]);

  return (
    <div class="settings-menu-anchor" ref={rootRef}>
      <Badge
        value={<GearIcon />}
        title="settings"
        variant="quiet"
        onClick={() => setOpen((v) => !v)}
        expanded={open}
      />
      {open ? (
        <div class="settings-menu-popover" role="menu" aria-label="settings">
          <label class="settings-menu-row">
            <span>theme</span>
            <select
              value={theme}
              onChange={(e) =>
                setTheme((e.target as HTMLSelectElement).value as ThemeOverride)
              }
            >
              {THEME_OPTIONS.map((o) => (
                <option key={o} value={o}>
                  {o}
                </option>
              ))}
            </select>
          </label>
          <label class="settings-menu-row">
            <span>motion</span>
            <select
              value={motion}
              onChange={(e) =>
                setMotion(
                  (e.target as HTMLSelectElement).value as MotionOverride,
                )
              }
            >
              {MOTION_OPTIONS.map((o) => (
                <option key={o} value={o}>
                  {o}
                </option>
              ))}
            </select>
          </label>
          {children}
        </div>
      ) : null}
    </div>
  );
}
