<script lang="ts">
  import { appRpc } from './rpc.ts';
  import { appState } from './app-state.svelte.ts';

  interface Props {
    groupId: string;
    projectId: string;
    /** Agent ID for this project's perspective (defaults to 'admin'). */
    agentId?: string;
  }

  let { groupId, projectId, agentId = 'admin' }: Props = $props();

  // Read comms state from project state tree
  function getComms() { return appState.project.getState(projectId).comms; }

  // ── Data fetching ────────────────────────────────────────────────────

  async function loadChannels() {
    try {
      const res = await appRpc.request['btmsg.listChannels']({ groupId });
      appState.project.comms.setState(projectId, 'channels', res.channels);
      const c = getComms();
      if (c.channels.length > 0 && !c.activeChannelId) {
        appState.project.comms.setState(projectId, 'activeChannelId', c.channels[0].id);
        await loadChannelMessages(c.channels[0].id);
      }
    } catch (err) {
      console.error('[CommsTab] loadChannels:', err);
    }
  }

  async function loadAgents() {
    try {
      const res = await appRpc.request['btmsg.getAgents']({ groupId });
      appState.project.comms.setState(projectId, 'agents',
        res.agents.filter((a: { id: string }) => a.id !== agentId));
    } catch (err) {
      console.error('[CommsTab] loadAgents:', err);
    }
  }

  async function loadChannelMessages(channelId: string) {
    try {
      appState.project.comms.setState(projectId, 'loading', true);
      const res = await appRpc.request['btmsg.getChannelMessages']({
        channelId, limit: 100,
      });
      appState.project.comms.setState(projectId, 'channelMessages', res.messages);
    } catch (err) {
      console.error('[CommsTab] loadChannelMessages:', err);
    } finally {
      appState.project.comms.setState(projectId, 'loading', false);
    }
  }

  async function loadDmMessages(otherId: string) {
    try {
      appState.project.comms.setState(projectId, 'loading', true);
      const res = await appRpc.request['btmsg.listMessages']({
        agentId, otherId, limit: 50,
      });
      appState.project.comms.setState(projectId, 'dmMessages', res.messages);
    } catch (err) {
      console.error('[CommsTab] loadDmMessages:', err);
    } finally {
      appState.project.comms.setState(projectId, 'loading', false);
    }
  }

  function selectChannel(id: string) {
    appState.project.comms.setMulti(projectId, { activeChannelId: id, showMembers: false });
    loadChannelMessages(id);
    loadChannelMembers(id);
  }

  async function loadChannelMembers(channelId: string) {
    try {
      const res = await appRpc.request['btmsg.getChannelMembers']({ channelId });
      appState.project.comms.setState(projectId, 'channelMembers', res.members);
    } catch (err) {
      console.error('[CommsTab] loadChannelMembers:', err);
    }
  }

  function selectDm(otherId: string) {
    appState.project.comms.setState(projectId, 'activeDmAgentId', otherId);
    loadDmMessages(otherId);
  }

  async function sendMessage() {
    const c = getComms();
    const text = c.input.trim();
    if (!text) return;
    appState.project.comms.setState(projectId, 'input', '');

    try {
      if (c.mode === 'channels' && c.activeChannelId) {
        await appRpc.request['btmsg.sendChannelMessage']({
          channelId: c.activeChannelId, fromAgent: agentId, content: text,
        });
        await loadChannelMessages(c.activeChannelId);
      } else if (c.mode === 'dms' && c.activeDmAgentId) {
        await appRpc.request['btmsg.sendMessage']({
          fromAgent: agentId, toAgent: c.activeDmAgentId, content: text,
        });
        await loadDmMessages(c.activeDmAgentId);
      }
    } catch (err) {
      console.error('[CommsTab] sendMessage:', err);
    }
  }

  function handleKeydown(e: KeyboardEvent) {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault();
      sendMessage();
    }
  }

  // ── Init + event-driven updates (Feature 4) ─────────────────────────

  let pollTimer: ReturnType<typeof setInterval> | null = null;

  function onNewMessage(payload: { groupId: string; channelId?: string }) {
    const c = getComms();
    if (c.mode === 'channels' && c.activeChannelId) {
      if (!payload.channelId || payload.channelId === c.activeChannelId) {
        loadChannelMessages(c.activeChannelId);
      }
    } else if (c.mode === 'dms' && c.activeDmAgentId) {
      loadDmMessages(c.activeDmAgentId);
    }
  }

  import { onMount } from 'svelte';
  onMount(() => {
    loadChannels();
    loadAgents();
    appRpc.addMessageListener('btmsg.newMessage', onNewMessage);
    pollTimer = setInterval(() => {
      const c = getComms();
      if (c.mode === 'channels' && c.activeChannelId) {
        loadChannelMessages(c.activeChannelId);
      } else if (c.mode === 'dms' && c.activeDmAgentId) {
        loadDmMessages(c.activeDmAgentId);
      }
    }, 30000);
    return () => {
      if (pollTimer) clearInterval(pollTimer);
      appRpc.removeMessageListener?.('btmsg.newMessage', onNewMessage);
    };
  });
</script>

<div class="comms-tab">
  <!-- Mode toggle -->
  <div class="comms-mode-bar">
    <button
      class="mode-btn"
      class:active={getComms().mode === 'channels'}
      onclick={() => { appState.project.comms.setState(projectId, 'mode', 'channels'); }}
    >Channels</button>
    <button
      class="mode-btn"
      class:active={getComms().mode === 'dms'}
      onclick={() => { appState.project.comms.setState(projectId, 'mode', 'dms'); loadAgents(); }}
    >DMs</button>
  </div>

  <div class="comms-body">
    <!-- Sidebar: channel list or agent list -->
    <div class="comms-sidebar">
      {#if getComms().mode === 'channels'}
        {#each getComms().channels as ch}
          <button
            class="sidebar-item"
            class:active={getComms().activeChannelId === ch.id}
            onclick={() => selectChannel(ch.id)}
          >
            <span class="ch-hash">#</span>
            <span class="ch-name">{ch.name}</span>
          </button>
        {/each}
        {#if getComms().channels.length === 0}
          <div class="sidebar-empty">No channels</div>
        {/if}
      {:else}
        {#each getComms().agents as ag}
          <button
            class="sidebar-item"
            class:active={getComms().activeDmAgentId === ag.id}
            onclick={() => selectDm(ag.id)}
          >
            <span class="agent-dot {ag.status}"></span>
            <span class="agent-name">{ag.name}</span>
            <span class="agent-role">{ag.role}</span>
            {#if ag.unreadCount > 0}
              <span class="unread-badge">{ag.unreadCount}</span>
            {/if}
          </button>
        {/each}
        {#if getComms().agents.length === 0}
          <div class="sidebar-empty">No agents</div>
        {/if}
      {/if}
    </div>

    <!-- Message area -->
    <div class="comms-messages">
      {#if getComms().loading}
        <div class="msg-loading">Loading...</div>
      {:else if getComms().mode === 'channels'}
        <div class="msg-list">
          {#each getComms().channelMessages as msg}
            <div class="msg-row">
              <span class="msg-sender">{msg.senderName}</span>
              <span class="msg-role">{msg.senderRole}</span>
              <span class="msg-time">{msg.createdAt.slice(11, 16)}</span>
              <div class="msg-content">{msg.content}</div>
            </div>
          {/each}
          {#if getComms().channelMessages.length === 0}
            <div class="msg-empty">No messages in this channel</div>
          {/if}
        </div>
      {:else}
        <div class="msg-list">
          {#each getComms().dmMessages as msg}
            <div class="msg-row" class:msg-mine={msg.fromAgent === agentId}>
              <span class="msg-sender">{msg.senderName ?? msg.fromAgent}</span>
              <span class="msg-time">{msg.createdAt.slice(11, 16)}</span>
              <div class="msg-content">{msg.content}</div>
            </div>
          {/each}
          {#if getComms().dmMessages.length === 0 && getComms().activeDmAgentId}
            <div class="msg-empty">No messages yet</div>
          {/if}
          {#if !getComms().activeDmAgentId}
            <div class="msg-empty">Select an agent to message</div>
          {/if}
        </div>
      {/if}

      <!-- Feature 7: Channel member list toggle -->
      {#if getComms().mode === 'channels' && getComms().activeChannelId}
        <button class="members-toggle" onclick={() => appState.project.comms.setState(projectId, 'showMembers', !getComms().showMembers)}>
          Members ({getComms().channelMembers.length})
        </button>
        {#if getComms().showMembers}
          <div class="members-list">
            {#each getComms().channelMembers as m}
              <span class="member-chip">{m.name} <span class="member-role">{m.role}</span></span>
            {/each}
          </div>
        {/if}
      {/if}

      <!-- Input bar -->
      <div class="msg-input-bar">
        <input
          class="msg-input"
          type="text"
          placeholder={getComms().mode === 'channels' ? 'Message channel...' : 'Send DM...'}
          value={getComms().input}
          oninput={(e) => appState.project.comms.setState(projectId, 'input', (e.target as HTMLInputElement).value)}
          onkeydown={handleKeydown}
        />
        <button class="msg-send-btn" onclick={sendMessage} disabled={!getComms().input.trim()}>
          Send
        </button>
      </div>
    </div>
  </div>
</div>

<style>
  .comms-tab {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    overflow: hidden;
  }

  .comms-mode-bar {
    display: flex;
    gap: 0.125rem;
    padding: 0.25rem;
    background: var(--ctp-mantle);
    border-bottom: 1px solid var(--ctp-surface0);
    flex-shrink: 0;
  }

  .mode-btn {
    flex: 1;
    padding: 0.25rem 0.5rem;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 0.25rem;
    color: var(--ctp-subtext0);
    font-family: var(--ui-font-family);
    font-size: 0.75rem;
    cursor: pointer;
    transition: background 0.12s, color 0.12s;
  }

  .mode-btn:hover { color: var(--ctp-text); }
  .mode-btn.active {
    background: var(--ctp-surface0);
    color: var(--ctp-text);
    border-color: var(--ctp-surface1);
  }

  .comms-body {
    display: flex;
    flex: 1;
    min-height: 0;
    overflow: hidden;
  }

  .comms-sidebar {
    width: 10rem;
    flex-shrink: 0;
    border-right: 1px solid var(--ctp-surface0);
    overflow-y: auto;
    padding: 0.25rem 0;
    background: var(--ctp-mantle);
  }

  .sidebar-item {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    width: 100%;
    padding: 0.375rem 0.5rem;
    background: transparent;
    border: none;
    color: var(--ctp-subtext0);
    font-family: var(--ui-font-family);
    font-size: 0.75rem;
    cursor: pointer;
    text-align: left;
    transition: background 0.1s;
  }

  .sidebar-item:hover { background: var(--ctp-surface0); color: var(--ctp-text); }
  .sidebar-item.active { background: var(--ctp-surface0); color: var(--ctp-text); }

  .ch-hash {
    color: var(--ctp-overlay0);
    font-weight: 700;
    flex-shrink: 0;
  }

  .ch-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  .agent-dot {
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--ctp-overlay0);
    flex-shrink: 0;
  }

  .agent-dot.active  { background: var(--ctp-green); }
  .agent-dot.running { background: var(--ctp-green); }
  .agent-dot.stopped { background: var(--ctp-overlay0); }

  .agent-name {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .agent-role {
    font-size: 0.625rem;
    color: var(--ctp-overlay0);
    flex-shrink: 0;
  }

  .unread-badge {
    background: var(--ctp-red);
    color: var(--ctp-base);
    font-size: 0.5625rem;
    font-weight: 700;
    padding: 0 0.25rem;
    border-radius: 0.5rem;
    min-width: 0.875rem;
    text-align: center;
    flex-shrink: 0;
  }

  .sidebar-empty {
    padding: 1rem 0.5rem;
    color: var(--ctp-overlay0);
    font-size: 0.75rem;
    font-style: italic;
    text-align: center;
  }

  .comms-messages {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0;
    overflow: hidden;
  }

  .msg-list {
    flex: 1;
    overflow-y: auto;
    padding: 0.5rem;
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
  }

  .msg-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    align-items: baseline;
  }

  .msg-mine { flex-direction: row-reverse; }

  .msg-sender {
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--ctp-blue);
    flex-shrink: 0;
  }

  .msg-role {
    font-size: 0.5625rem;
    color: var(--ctp-overlay0);
    flex-shrink: 0;
  }

  .msg-time {
    font-size: 0.5625rem;
    color: var(--ctp-overlay0);
    flex-shrink: 0;
    margin-left: auto;
  }

  .msg-content {
    width: 100%;
    font-size: 0.8125rem;
    color: var(--ctp-text);
    line-height: 1.4;
    word-break: break-word;
  }

  .msg-empty, .msg-loading {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--ctp-overlay0);
    font-size: 0.8125rem;
    font-style: italic;
  }

  .msg-input-bar {
    display: flex;
    gap: 0.25rem;
    padding: 0.375rem;
    border-top: 1px solid var(--ctp-surface0);
    background: var(--ctp-mantle);
    flex-shrink: 0;
  }

  .msg-input {
    flex: 1;
    height: 1.75rem;
    background: var(--ctp-surface0);
    border: 1px solid var(--ctp-surface1);
    border-radius: 0.25rem;
    color: var(--ctp-text);
    font-family: var(--ui-font-family);
    font-size: 0.8125rem;
    padding: 0 0.5rem;
    outline: none;
  }

  .msg-input:focus { border-color: var(--ctp-mauve); }

  .msg-send-btn {
    padding: 0 0.625rem;
    height: 1.75rem;
    background: color-mix(in srgb, var(--ctp-blue) 20%, transparent);
    border: 1px solid var(--ctp-blue);
    border-radius: 0.25rem;
    color: var(--ctp-blue);
    font-family: var(--ui-font-family);
    font-size: 0.75rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.1s;
    flex-shrink: 0;
  }

  .msg-send-btn:hover:not(:disabled) {
    background: color-mix(in srgb, var(--ctp-blue) 35%, transparent);
  }

  .msg-send-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
  }

  /* Feature 7: Member list */
  .members-toggle {
    background: var(--ctp-surface0);
    border: none;
    border-top: 1px solid var(--ctp-surface0);
    padding: 0.25rem 0.5rem;
    font-size: 0.625rem;
    color: var(--ctp-overlay1);
    cursor: pointer;
    text-align: left;
    font-family: var(--ui-font-family);
  }

  .members-toggle:hover { color: var(--ctp-text); }

  .members-list {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    padding: 0.25rem 0.5rem;
    background: var(--ctp-surface0);
    border-top: 1px solid var(--ctp-surface0);
  }

  .member-chip {
    font-size: 0.625rem;
    color: var(--ctp-text);
    background: var(--ctp-mantle);
    padding: 0.125rem 0.375rem;
    border-radius: 0.25rem;
    border: 1px solid var(--ctp-surface1);
  }

  .member-role {
    color: var(--ctp-overlay0);
    font-size: 0.5625rem;
  }
</style>
