/* Dispatch — Slack inbox
 * Loaded by index.html after lib.jsx.
 *
 * Replicates the original SlackInboxView: a two-pane layout — the message list
 * on the left, and a conversation panel on the right (the Slack thread as a
 * chatbox, with a reply box, plus convert-to-ticket / dismiss actions). Data:
 * fetchSlackInbox(status) for the list, fetchSlackInboxThread /
 * replySlackInboxThread for the conversation, convertSlackInboxToHelpdesk /
 * dismissSlackInbox for the decision — same as the original SlackInboxDetail. */

const slkInitials = (name) => (name || '?').split(/[\s_.-]+/).filter(Boolean).slice(0, 2).map(p => p[0]).join('').toUpperCase() || '?';
const slkAuthor = (i) => i.authorName || i.authorUserId || 'Slack user';
const slkMsgAuthor = (m) => m.authorName || m.userName || m.author || m.user || 'user';
const SLK_STATUSES = [['pending', 'Pending'], ['converted_helpdesk', 'Converted'], ['dismissed', 'Dismissed']];
const SLK_TRIGGERS = [['all', 'All'], ['mention', '@dispatch'], ['reaction', '👀']];

// Right pane: the Slack thread as a chatbox + reply + convert/dismiss.
function SlackConversation({ item, onDecided }) {
  const [thread, setThread] = useState(null);
  const [loading, setLoading] = useState(true);
  const [threadError, setThreadError] = useState(null);
  const [reply, setReply] = useState('');
  const [replying, setReplying] = useState(false);
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState(null);
  const [title, setTitle] = useState('');
  const [priority, setPriority] = useState('medium');
  const [category, setCategory] = useState('general');

  async function loadThread() {
    setLoading(true);
    try { setThread(await api.fetchSlackInboxThread(item.id)); setThreadError(null); }
    catch (e) { setThreadError(e.message || 'Could not load Slack thread'); }
    finally { setLoading(false); }
  }
  useEffect(() => {
    setTitle((item.text || '').split('\n')[0].trim().slice(0, 120) || 'Slack request');
    setPriority('medium'); setCategory('general'); setReply(''); setError(null);
    loadThread();
  }, [item.id]);

  async function sendReply() {
    const text = reply.trim();
    if (!text) return;
    setReplying(true); setThreadError(null);
    try { await api.replySlackInboxThread(item.id, text); setReply(''); await loadThread(); }
    catch (e) { setThreadError(e.message || 'Reply failed'); }
    finally { setReplying(false); }
  }
  async function convert() {
    setBusy(true); setError(null);
    try { const r = await api.convertSlackInboxToHelpdesk(item.id, { title: title.trim(), priority, category }); onDecided(r.item || { ...item, status: 'converted_helpdesk' }); }
    catch (e) { setError(e.message || 'Convert failed'); }
    finally { setBusy(false); }
  }
  async function dismiss() {
    setBusy(true); setError(null);
    try { const r = await api.dismissSlackInbox(item.id); onDecided(r.item || { ...item, status: 'dismissed' }); }
    catch (e) { setError(e.message || 'Dismiss failed'); }
    finally { setBusy(false); }
  }

  const messages = (thread && thread.messages) || [];
  const pending = item.status === 'pending';

  return (
    <Card className="flex h-[70vh] min-h-[480px] flex-col">
      {/* Conversation header */}
      <div className="flex items-center gap-2 border-b p-3">
        <div className="flex h-8 w-8 items-center justify-center rounded-full bg-muted text-xs font-semibold">{slkInitials(slkAuthor(item))}</div>
        <div className="min-w-0 flex-1">
          <div className="truncate text-sm font-medium">{slkAuthor(item)}</div>
          <div className="truncate text-xs text-muted-foreground">{item.channelName ? `#${item.channelName}` : 'Slack'} · {relAge(item.createdAt)} ago</div>
        </div>
        {item.permalink && <a href={item.permalink} target="_blank" rel="noreferrer" className="text-xs text-muted-foreground hover:text-foreground">Open in Slack ↗</a>}
      </div>

      {/* Chat transcript */}
      <div className="flex-1 space-y-2 overflow-y-auto bg-muted/20 p-3">
        {threadError && <div className="rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive">{threadError}</div>}
        {loading && messages.length === 0 && <div className="text-sm text-muted-foreground">Loading conversation…</div>}
        {!loading && messages.length === 0 && !threadError && (
          <div className="rounded-lg bg-background p-3 shadow-sm">
            <div className="flex justify-between text-xs"><strong>{slkAuthor(item)}</strong></div>
            <div className="mt-0.5 whitespace-pre-wrap text-sm">{item.text}</div>
          </div>
        )}
        {messages.map((m, i) => (
          <div key={i} className="rounded-lg bg-background p-3 shadow-sm">
            <div className="flex items-baseline justify-between gap-2">
              <strong className="text-xs">{slkMsgAuthor(m)}</strong>
              {m.ts && <span className="text-[10px] text-muted-foreground">{m.ts}</span>}
            </div>
            <div className="mt-0.5 whitespace-pre-wrap text-sm">{m.text}</div>
          </div>
        ))}
      </div>

      {/* Reply box (posts into the Slack thread) */}
      <div className="flex items-end gap-2 border-t p-3">
        <Textarea className="min-h-[40px] flex-1" rows="1" placeholder="Reply in the Slack thread…" value={reply} onChange={e => setReply(e.target.value)} />
        <Button disabled={replying || !reply.trim()} onClick={sendReply}>{replying ? 'Sending…' : 'Reply'}</Button>
      </div>

      {/* Decision */}
      {pending ? (
        <div className="space-y-3 border-t bg-muted/30 p-3">
          {error && <div className="rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive">{error}</div>}
          <div className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">Convert to Help Desk</div>
          <Input value={title} onChange={e => setTitle(e.target.value)} placeholder="Ticket title" />
          <div className="flex flex-wrap items-center gap-2">
            <Select className="w-32" value={priority} onChange={e => setPriority(e.target.value)}>{['low', 'medium', 'high', 'critical'].map(p => <option key={p} value={p}>{titleCase(p)}</option>)}</Select>
            <Select className="w-36" value={category} onChange={e => setCategory(e.target.value)}>{['general', 'bug', 'feature', 'question', 'access'].map(c => <option key={c} value={c}>{titleCase(c)}</option>)}</Select>
            <Button className="ml-auto" disabled={busy || !title.trim()} onClick={convert}>Convert to ticket</Button>
            <Button variant="outline" disabled={busy} onClick={dismiss}>Dismiss</Button>
          </div>
        </div>
      ) : (
        <div className="border-t p-3 text-sm text-muted-foreground">
          <Badge variant="outline">{(item.status || '').replace('_', ' ')}</Badge>
          {item.linkedTicketId && <span className="ml-2">Ticket {String(item.linkedTicketId).slice(0, 8)}</span>}
          {item.linkedGithubIssueNumber && <span className="ml-2">GH #{item.linkedGithubIssueNumber}</span>}
        </div>
      )}
    </Card>
  );
}

function SlackInbox() {
  const [statusFilter, setStatusFilter] = useState('pending');
  const [triggerFilter, setTriggerFilter] = useState('all');
  const [items, setItems] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [selId, setSelId] = useState(null);
  const [page, setPage] = useState(1);
  const [overviewOpen, setOverviewOpen] = useOverviewOpen();

  async function reload() {
    setLoading(true);
    try {
      const list = await api.fetchSlackInbox(statusFilter);
      const arr = Array.isArray(list) ? list : (list.items || []);
      setItems(arr); setError(null); setSelId(arr[0] ? arr[0].id : null);
    } catch (e) { setError(e.message || 'Failed to load Slack inbox'); }
    finally { setLoading(false); }
  }
  useEffect(() => { reload(); }, [statusFilter]);
  useEffect(() => { setPage(1); }, [statusFilter, triggerFilter]);

  const filtered = items.filter(i => triggerFilter === 'all' || i.triggerType === triggerFilter);
  const pageCount = Math.max(1, Math.ceil(filtered.length / PER_PAGE));
  const paged = filtered.slice((page - 1) * PER_PAGE, page * PER_PAGE);
  const sel = items.find(i => i.id === selId);

  function onDecided(updated) {
    if (statusFilter === 'pending') { setItems(prev => prev.filter(x => x.id !== (updated && updated.id))); setSelId(null); }
    else if (updated) setItems(prev => prev.map(x => x.id === updated.id ? updated : x));
  }

  const Seg = ({ opts, value, onChange }) => (
    <div className="inline-flex flex-wrap gap-1 rounded-lg bg-muted p-1">
      {opts.map(([k, label]) => (
        <button key={k} onClick={() => onChange(k)}
          className={cn('rounded-md px-3 py-1 text-sm font-medium transition-colors', value === k ? 'bg-background text-foreground shadow' : 'text-muted-foreground hover:text-foreground')}>{label}</button>
      ))}
    </div>
  );

  return (
    <div className="space-y-4">
      {overviewOpen && (
        <Card className="border-primary/20 bg-primary/5">
          <CardContent className="pt-6">
            <h2 className="text-2xl font-semibold tracking-tight">Slack inbox</h2>
            <p className="mt-1 text-sm text-muted-foreground">Messages flagged from Slack via an @dispatch mention or a trigger emoji. Open one to read the thread, reply, then convert it to a Help Desk ticket or dismiss it.</p>
          </CardContent>
        </Card>
      )}

      <div className="flex flex-wrap items-center gap-2">
        <Seg opts={SLK_STATUSES} value={statusFilter} onChange={setStatusFilter} />
        <Seg opts={SLK_TRIGGERS} value={triggerFilter} onChange={setTriggerFilter} />
      </div>

      {error && <div className="rounded-md border border-amber-300 bg-amber-50 px-4 py-2 text-sm text-amber-800">{error}</div>}

      {/* Two-pane: message list (left) + conversation (right). */}
      <div className="grid gap-4 lg:grid-cols-[minmax(0,380px)_minmax(0,1fr)]">
        <Card className="flex h-[70vh] min-h-[480px] flex-col">
          <div className="flex-1 divide-y overflow-y-auto">
            {loading && filtered.length === 0 && <div className="p-4 text-sm text-muted-foreground">Loading…</div>}
            {!loading && filtered.length === 0 && <div className="p-6 text-center text-sm text-muted-foreground">{statusFilter === 'pending' ? 'Inbox zero — nothing awaiting triage.' : 'Nothing here.'}</div>}
            {paged.map(i => (
              <button key={i.id} onClick={() => setSelId(i.id)}
                className={cn('flex w-full items-start gap-3 p-3 text-left transition-colors hover:bg-muted/50', selId === i.id && 'bg-muted/60')}>
                <div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-muted text-xs font-semibold">{slkInitials(slkAuthor(i))}</div>
                <div className="min-w-0 flex-1">
                  <div className="flex flex-wrap items-center gap-1.5">
                    <strong className="truncate text-sm">{slkAuthor(i)}</strong>
                    {i.triggerType === 'mention' && <Badge variant="secondary">@dispatch</Badge>}
                    {i.triggerType === 'reaction' && <Badge variant="secondary">:{i.triggerReaction || 'emoji'}:</Badge>}
                    <span className="ml-auto text-xs text-muted-foreground">{relAge(i.createdAt)}</span>
                  </div>
                  <div className="mt-0.5 line-clamp-2 text-sm text-muted-foreground">{i.text}</div>
                </div>
              </button>
            ))}
          </div>
          <div className="flex items-center justify-between border-t px-3 py-2 text-xs text-muted-foreground">
            <span>{filtered.length}</span>
            <Pagination page={page} pageCount={pageCount} onPage={setPage} />
          </div>
        </Card>

        {sel
          ? <SlackConversation key={sel.id} item={sel} onDecided={onDecided} />
          : <Card className="flex h-[70vh] min-h-[480px] items-center justify-center"><div className="p-8 text-center text-sm text-muted-foreground">Pick a message to read the conversation.</div></Card>}
      </div>
    </div>
  );
}
