'use client';

/**
 * `<SlashMenu>` — the filtered command list shown above the composer
 * while the slash machine is in `composing` state.
 *
 * Keyboard navigation (↑/↓/Enter/Tab/Esc) is owned by
 * `useSlashCommands` — this component is a pure render of the
 * `matches` + `highlight` it produces, plus click/hover handlers.
 *
 * Empty matches still render (showing a muted "No commands match" line)
 * — keeps the dropdown anchored while the user fixes a typo instead of
 * silently disappearing on them.
 */
import { forwardRef } from 'react';

import { cn } from '@djangocfg/ui-core/lib';

import {
  DEFAULT_SLASH_LABELS,
  formatEmptyState,
  type SlashMenuLabels,
} from './labels';
import type { SlashCommand } from './types';

export interface SlashMenuProps {
  /** Filtered verbs to show (from `useSlashCommands.matches`). */
  matches: readonly SlashCommand[];
  /** Index of the highlighted row. */
  highlight: number;
  /** Current filter query — only used for the empty-state line. */
  query?: string;
  /** Called when a row is clicked. */
  onPick: (command: SlashCommand) => void;
  /** Optional pointer-move highlight sync. */
  onHighlight?: (index: number) => void;
  /** Localised label overrides for the empty state. */
  labels?: Partial<SlashMenuLabels>;
  className?: string;
}

export const SlashMenu = forwardRef<HTMLDivElement, SlashMenuProps>(
  function SlashMenu(
    {
      matches,
      highlight,
      query = '',
      onPick,
      onHighlight,
      labels,
      className,
    },
    ref,
  ) {
    const L = { ...DEFAULT_SLASH_LABELS, ...labels };
    const isEmpty = matches.length === 0;

    return (
      <div
        ref={ref}
        role="listbox"
        aria-label="Slash commands"
        className={cn(
          'overflow-hidden rounded-xl bg-popover text-popover-foreground',
          'ring-1 ring-border shadow-lg shadow-black/10',
          className,
        )}
      >
        <div className="p-1">
          {isEmpty ? (
            <div
              role="option"
              aria-disabled
              aria-selected={false}
              className="px-2 py-1.5 text-[12px] text-muted-foreground"
            >
              {formatEmptyState(L.emptyState, query)}
            </div>
          ) : (
            matches.map((cmd, i) => {
              const isActive = i === highlight;
              return (
                <button
                  key={cmd.id}
                  type="button"
                  role="option"
                  aria-selected={isActive}
                  onMouseDown={(e) => {
                    // Keep focus in the editor — submit/blur must not fire.
                    e.preventDefault();
                    onPick(cmd);
                  }}
                  onMouseEnter={() => onHighlight?.(i)}
                  onMouseMove={() => onHighlight?.(i)}
                  className={cn(
                    'flex w-full items-center gap-2.5 rounded-lg px-2 py-1.5 text-left transition-colors',
                    isActive ? 'bg-accent' : 'hover:bg-accent/60',
                  )}
                >
                  {cmd.icon ? (
                    <span
                      className={cn(
                        'flex h-6 w-6 shrink-0 items-center justify-center rounded-md',
                        'bg-muted/40 text-primary',
                      )}
                    >
                      {cmd.icon}
                    </span>
                  ) : null}
                  {/* Header + description form one tight group; the icon
                      is the visual anchor, the token is a structural
                      label. Column auto-sizes — no dead air between
                      `/clear` and "Clear conversation". */}
                  <span className="flex min-w-0 flex-col gap-0.5">
                    <span className="flex items-baseline gap-2">
                      <span className="text-[12px] font-semibold text-foreground">
                        {cmd.token}
                      </span>
                      {cmd.argHint ? (
                        <span className="text-[11px] text-muted-foreground/60">
                          {cmd.argHint}
                        </span>
                      ) : null}
                      <span className="truncate text-[12px] text-muted-foreground">
                        {cmd.label}
                      </span>
                    </span>
                    {cmd.description ? (
                      <span className="truncate text-[11px] text-muted-foreground/70">
                        {cmd.description}
                      </span>
                    ) : null}
                  </span>
                </button>
              );
            })
          )}
        </div>
      </div>
    );
  },
);
