// <TermInput> — the fixed composer at the bottom of the page. Sends a
// plain message to this agent's own turn loop (`POST send`), or
// intercepts a `/slash` command locally (never sent to the agent).
// Ported from app.js's `renderTermInput`/`handleSlashCommand`/
// `completeSlash`, with one deliberate UX change: `/new-session` and
// `/logout` used to pop the old shadow-DOM `themedConfirm` modal
// (@hive/shared/modal.js) before firing — this rewrite's destructive
// actions all avoid that widget family (see SidePanel.tsx's/
// useConfirmClick.ts's file comments for why), and a modal doesn't fit
// a text-input flow anyway. Instead: typing the command once arms it
// (a local note explains what confirming does), typing it again within
// the same "armed" state fires it — a keyboard-native two-step confirm.
import { useRef, useState } from 'preact/hooks';
import { postModel, postEffort } from '../lib/modelEffort.js';
import { postCancelTurn, postCompact, postNewSession, postLogout, postSend } from '../lib/termActions.js';

export interface TermInputProps {
  label: string;
  online: boolean;
  onLocalNote: (text: string) => void;
  onClear: () => void;
}

const SLASH_COMMANDS: { name: string; desc: string }[] = [
  { name: '/help', desc: 'list slash commands' },
  { name: '/clear', desc: 'wipe the terminal panel (local-only)' },
  { name: '/cancel', desc: 'SIGINT the in-flight claude turn' },
  { name: '/compact', desc: 'compact the persistent claude session' },
  { name: '/model', desc: '/model <name>  — switch claude model for future turns' },
  { name: '/effort', desc: '/effort <level>  — set claude effort (medium/high/xhigh) for future turns' },
  { name: '/new-session', desc: 'fresh claude session next turn (type twice to confirm)' },
  { name: '/logout', desc: 'rotate OAuth creds + park in needs-login (type twice to confirm)' },
];

const MAX_PX = 12 * 16; // ~8 lines @ 1.5 line-height, 1em base

function completeSlash(prefix: string): string | null {
  const matches = SLASH_COMMANDS.filter((c) => c.name.startsWith(prefix));
  if (!matches.length) return null;
  const idx = matches.findIndex((c) => c.name === prefix);
  return matches[(idx + 1) % matches.length].name;
}

export function TermInput({ label, online, onLocalNote, onClear }: TermInputProps) {
  const [value, setValue] = useState('');
  const taRef = useRef<HTMLTextAreaElement>(null);
  // Which destructive command is currently "armed" (typed once, waiting
  // for the confirming repeat) — any other command clears it.
  const armedRef = useRef<string | null>(null);

  function grow() {
    const ta = taRef.current;
    if (!ta) return;
    ta.style.height = 'auto';
    ta.style.height = Math.min(ta.scrollHeight, MAX_PX) + 'px';
  }

  function reportFailure(label_: string, detail?: string) {
    onLocalNote(`✗ ${label_} failed${detail ? ': ' + detail : ''}`);
  }

  function handleSlash(line: string): boolean {
    const trimmed = line.trim();
    const [cmd, ...rest] = trimmed.split(/\s+/);
    const arg = rest.join(' ');
    const wasArmed = armedRef.current === cmd;
    armedRef.current = null;

    switch (cmd) {
      case '/help':
        onLocalNote('/help');
        for (const c of SLASH_COMMANDS) onLocalNote(`    ${c.name.padEnd(13)} — ${c.desc}`);
        return true;
      case '/clear':
        onClear();
        onLocalNote('· terminal cleared (local view only — server history kept)');
        return true;
      case '/cancel':
        postCancelTurn().then((r) => !r.ok && reportFailure('/cancel', r.detail));
        return true;
      case '/compact':
        postCompact().then((r) => !r.ok && reportFailure('/compact', r.detail));
        return true;
      case '/new-session':
        if (wasArmed) {
          postNewSession().then((r) => !r.ok && reportFailure('/new-session', r.detail));
        } else {
          armedRef.current = '/new-session';
          onLocalNote('⚠ drops all prior --continue context. type /new-session again to confirm.');
        }
        return true;
      case '/logout':
        if (wasArmed) {
          postLogout().then((r) => !r.ok && reportFailure('/logout', r.detail));
        } else {
          armedRef.current = '/logout';
          onLocalNote('⚠ SIGINTs the current turn + rotates OAuth credentials. type /logout again to confirm.');
        }
        return true;
      case '/model':
        if (!arg) onLocalNote('✗ /model needs a name (e.g. /model haiku, /model sonnet, /model opus)');
        else postModel(arg).then((r) => !r.ok && reportFailure('/model', r.detail));
        return true;
      case '/effort':
        if (!arg) onLocalNote('✗ /effort needs a level (e.g. /effort medium, /effort high, /effort xhigh)');
        else postEffort(arg).then((r) => !r.ok && reportFailure('/effort', r.detail));
        return true;
      default:
        onLocalNote(`✗ unknown slash command: ${cmd} — try /help`);
        return true;
    }
  }

  function submit() {
    const line = value;
    if (!line.trim()) return;
    setValue('');
    requestAnimationFrame(grow);
    if (line.trim().startsWith('/')) {
      handleSlash(line);
      return;
    }
    armedRef.current = null;
    postSend(line).then((r) => !r.ok && reportFailure('send', r.detail));
  }

  function onInput(e: Event) {
    setValue((e.currentTarget as HTMLTextAreaElement).value);
    grow();
  }

  function onKeyDown(e: KeyboardEvent) {
    if (e.key === 'Tab' && value.startsWith('/') && !value.includes(' ')) {
      const next = completeSlash(value);
      if (next) {
        e.preventDefault();
        setValue(next);
      }
      return;
    }
    if (e.key === 'Enter' && !e.shiftKey && !e.isComposing) {
      e.preventDefault();
      submit();
    }
  }

  return (
    <div class={`term-input${online ? '' : ' disabled'}`}>
      <form
        class="sendform-term"
        onSubmit={(e) => {
          e.preventDefault();
          submit();
        }}
      >
        <span class="prompt">operator@{label} ▸</span>
        <textarea
          ref={taRef}
          value={value}
          placeholder={`message ${label}…`}
          rows={1}
          disabled={!online}
          autocomplete="off"
          onInput={onInput}
          onKeyDown={onKeyDown}
        />
        <span class="submit-hint">↵ send · ⇧↵ newline · /help</span>
      </form>
    </div>
  );
}
