import { useMemo, useRef, useState, type ChangeEvent, type FormEvent, type KeyboardEvent } from 'react';
import {
  SPECIAL_MENTIONS,
  insertMention,
  resolveMentions,
  trailingMentionQuery,
} from '../mentions';
import type { Attachment, Person, SendOpts } from '../types';

interface Suggestion {
  key: string;
  label: string;
  insert: string;
}

/**
 * The message input: draft, @mention autocomplete, and attachment staging. Shared by the main
 * Thread and the ThreadPane (which passes a parentInteractionId so a reply lands in the thread).
 */
export function Composer({
  members,
  canUpload,
  upload,
  onSend,
  onTyping,
  parentInteractionId,
  placeholder = 'Type a message… @ to mention',
}: {
  members: Person[];
  canUpload: boolean;
  upload: (file: File) => Promise<Attachment>;
  onSend: (text: string, opts?: SendOpts) => Promise<void>;
  onTyping?: () => void;
  parentInteractionId?: string;
  placeholder?: string;
}) {
  const [draft, setDraft] = useState('');
  const [sending, setSending] = useState(false);
  const [staged, setStaged] = useState<Attachment | null>(null);
  const [uploading, setUploading] = useState(false);
  const fileRef = useRef<HTMLInputElement>(null);

  const query = trailingMentionQuery(draft);
  const suggestions = useMemo<Suggestion[]>(() => {
    if (query === null) return [];
    const q = query.toLowerCase();
    const specials = SPECIAL_MENTIONS.filter((s) => s.startsWith(q)).map((s) => ({ key: `@${s}`, label: `@${s}`, insert: s }));
    const people = members.filter((m) => m.name.toLowerCase().includes(q)).map((m) => ({ key: m.id, label: m.name, insert: m.name }));
    return [...specials, ...people].slice(0, 6);
  }, [query, members]);
  const showSuggest = query !== null && suggestions.length > 0;

  function pick(insert: string): void {
    setDraft((d) => insertMention(d, insert));
  }

  async function onPickFile(e: ChangeEvent<HTMLInputElement>): Promise<void> {
    const file = e.target.files?.[0];
    e.target.value = '';
    if (!file) return;
    setUploading(true);
    try {
      setStaged(await upload(file));
    } catch {
      /* host surfaces upload errors */
    } finally {
      setUploading(false);
    }
  }

  async function submit(e?: FormEvent): Promise<void> {
    e?.preventDefault();
    const text = draft.trim();
    if ((!text && !staged) || sending) return;
    const mentions = resolveMentions(text, members);
    const att = staged;
    setDraft('');
    setStaged(null);
    setSending(true);
    try {
      await onSend(text, {
        ...(mentions.length ? { mentions } : {}),
        ...(att ? { attachment: att } : {}),
        ...(parentInteractionId ? { parentInteractionId } : {}),
      });
    } catch {
      setStaged(att);
    } finally {
      setSending(false);
    }
  }

  function onKeyDown(e: KeyboardEvent<HTMLInputElement>): void {
    if (showSuggest && e.key === 'Enter') {
      e.preventDefault();
      pick(suggestions[0]!.insert);
    }
  }

  return (
    <form className="miu-composer" onSubmit={submit}>
      {showSuggest ? (
        <ul className="miu-suggest" role="listbox" aria-label="Mention suggestions">
          {suggestions.map((s) => (
            <li key={s.key}>
              <button type="button" role="option" aria-selected="false" className="miu-suggest-item" onClick={() => pick(s.insert)}>
                {s.label}
              </button>
            </li>
          ))}
        </ul>
      ) : null}
      {staged ? (
        <div className="miu-staged">
          📎 {staged.name}
          <button type="button" className="miu-staged-x" onClick={() => setStaged(null)} aria-label="Remove attachment">
            ✕
          </button>
        </div>
      ) : null}
      <div className="miu-composer-row">
        {canUpload ? (
          <>
            <input ref={fileRef} type="file" className="miu-file-input" onChange={onPickFile} aria-label="Attach a file" />
            <button type="button" className="miu-attach-btn" title="Attach a file" disabled={uploading} onClick={() => fileRef.current?.click()}>
              {uploading ? '…' : '📎'}
            </button>
          </>
        ) : null}
        <input
          className="miu-input"
          value={draft}
          placeholder={placeholder}
          aria-label="Message"
          onChange={(e) => {
            setDraft(e.target.value);
            onTyping?.();
          }}
          onKeyDown={onKeyDown}
        />
        <button type="submit" className="miu-send" disabled={(!draft.trim() && !staged) || sending}>
          Send
        </button>
      </div>
    </form>
  );
}
