import { useState } from 'react';

type EditableTitleProps = {
  /** What to show, and what the field opens on. */
  value: string;
  /** Called with the trimmed draft on Enter or blur, only when it actually differs from `value`. */
  onCommit: (next: string) => void;
  /**
   * Let an emptied field commit as `''`.
   *
   * Off by default, because for most titles empty is not a value — the chat rename endpoint 400s on it,
   * and there is nothing sensible to show. The nav header is the exception: clearing the field is how you
   * hand the tab back to the route's own name, and it is documented there as the only way out.
   */
  allowEmpty?: boolean;
  /** No edit affordance — renders as plain text. For a title with nothing behind it yet, like a new chat. */
  readOnly?: boolean;
  ariaLabel: string;
  /** Tooltip on the resting state. The edit affordance is invisible otherwise, so this is how it is found. */
  hint?: string;
  className?: string;
  inputClassName?: string;
};

/**
 * Click a title, type a new one.
 *
 * The edit is a **draft committed on blur/Enter**, not a live write. Writing every keystroke is fine
 * while a title is a plain string and stops being fine the moment empty means something — here it means
 * "keep what you had", so deleting the last character would otherwise snap the field to the old value
 * underneath the cursor. Escape discards.
 *
 * Extracted from the nav header's tab rename, which is now one of two callers. Deliberately not a third
 * caller: `SessionList`'s row rename is opened by a pencil button and confirmed by a check button, so it
 * is a different interaction wearing the same styling, and folding it in would mean an `isEditing` prop
 * that only one caller passes.
 */
export function EditableTitle({
  value,
  onCommit,
  allowEmpty,
  readOnly,
  ariaLabel,
  hint,
  className = '',
  inputClassName = '',
}: EditableTitleProps) {
  const [draft, setDraft] = useState<string | null>(null);

  if (readOnly) return <span className={className}>{value}</span>;

  if (draft !== null) {
    return (
      <input
        autoFocus
        value={draft}
        onChange={(ev) => setDraft(ev.target.value)}
        onBlur={() => {
          const next = draft.trim();
          if ((next || allowEmpty) && next !== value) onCommit(next);
          setDraft(null);
        }}
        onKeyDown={(ev) => {
          if (ev.key === 'Enter') ev.currentTarget.blur();
          if (ev.key === 'Escape') setDraft(null); // discard, keeping whatever it was called
        }}
        aria-label={ariaLabel}
        placeholder={value}
        className={inputClassName}
      />
    );
  }

  return (
    <button onClick={() => setDraft(value)} title={hint} className={className}>
      {value}
    </button>
  );
}
