<script lang="ts">
  import { appRpc } from './rpc.ts';

  // ── Types ────────────────────────────────────────────────────────────

  interface Channel {
    id: string;
    name: string;
    groupId: string;
    createdBy: string;
    memberCount: number;
    createdAt: string;
  }

  interface ChannelMessage {
    id: string;
    channelId: string;
    fromAgent: string;
    content: string;
    createdAt: string;
    senderName: string;
    senderRole: string;
  }

  interface Agent {
    id: string;
    name: string;
    role: string;
    groupId: string;
    tier: number;
    status: string;
    unreadCount: number;
  }

  interface DM {
    id: string;
    fromAgent: string;
    toAgent: string;
    content: string;
    read: boolean;
    createdAt: string;
    senderName: string | null;
    senderRole: string | null;
  }

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

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

  // ── State ────────────────────────────────────────────────────────────

  type TabMode = 'channels' | 'dms';
  let mode = $state<TabMode>('channels');

  let channels = $state<Channel[]>([]);
  let agents = $state<Agent[]>([]);
  let activeChannelId = $state<string | null>(null);
  let activeDmAgentId = $state<string | null>(null);
  let channelMessages = $state<ChannelMessage[]>([]);
  let dmMessages = $state<DM[]>([]);
  let input = $state('');
  let loading = $state(false);
  // Feature 7: Channel member list
  let channelMembers = $state<Array<{ agentId: string; name: string; role: string }>>([]);
  let showMembers = $state(false);

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

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

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

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

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

  function selectChannel(id: string) {
    activeChannelId = id;
    showMembers = false;
    loadChannelMessages(id);
    loadChannelMembers(id);
  }

  // Feature 7: Load channel members
  async function loadChannelMembers(channelId: string) {
    try {
      const res = await appRpc.request['btmsg.getChannelMembers']({ channelId });
      channelMembers = res.members;
    } catch (err) {
      console.error('[CommsTab] loadChannelMembers:', err);
    }
  }

  function selectDm(otherId: string) {
    activeDmAgentId = otherId;
    loadDmMessages(otherId);
  }

  async function sendMessage() {
    const text = input.trim();
    if (!text) return;
    input = '';

    try {
      if (mode === 'channels' && activeChannelId) {
        await appRpc.request['btmsg.sendChannelMessage']({
          channelId: activeChannelId, fromAgent: agentId, content: text,
        });
        await loadChannelMessages(activeChannelId);
      } else if (mode === 'dms' && activeDmAgentId) {
        await appRpc.request['btmsg.sendMessage']({
          fromAgent: agentId, toAgent: activeDmAgentId, content: text,
        });
        await loadDmMessages(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;

  // Feature 4: Listen for push events
  function onNewMessage(payload: { groupId: string; channelId?: string }) {
    if (mode === 'channels' && activeChannelId) {
      if (!payload.channelId || payload.channelId === activeChannelId) {
        loadChannelMessages(activeChannelId);
      }
    } else if (mode === 'dms' && activeDmAgentId) {
      loadDmMessages(activeDmAgentId);
    }
  }

  $effect(() => {
    loadChannels();
    loadAgents();
    appRpc.addMessageListener('btmsg.newMessage', onNewMessage);
    // Feature 4: Fallback 30s poll for missed events
    pollTimer = setInterval(() => {
      if (mode === 'channels' && activeChannelId) {
        loadChannelMessages(activeChannelId);
      } else if (mode === 'dms' && activeDmAgentId) {
        loadDmMessages(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={mode === 'channels'}
      onclick={() => { mode = 'channels'; }}
    >Channels</button>
    <button
      class="mode-btn"
      class:active={mode === 'dms'}
      onclick={() => { mode = 'dms'; loadAgents(); }}
    >DMs</button>
  </div>

  <div class="comms-body">
    <!-- Sidebar: channel list or agent list -->
    <div class="comms-sidebar">
      {#if mode === 'channels'}
        {#each channels as ch}
          <button
            class="sidebar-item"
            class:active={activeChannelId === ch.id}
            onclick={() => selectChannel(ch.id)}
          >
            <span class="ch-hash">#</span>
            <span class="ch-name">{ch.name}</span>
          </button>
        {/each}
        {#if channels.length === 0}
          <div class="sidebar-empty">No channels</div>
        {/if}
      {:else}
        {#each agents as ag}
          <button
            class="sidebar-item"
            class:active={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 agents.length === 0}
          <div class="sidebar-empty">No agents</div>
        {/if}
      {/if}
    </div>

    <!-- Message area -->
    <div class="comms-messages">
      {#if loading}
        <div class="msg-loading">Loading...</div>
      {:else if mode === 'channels'}
        <div class="msg-list">
          {#each 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 channelMessages.length === 0}
            <div class="msg-empty">No messages in this channel</div>
          {/if}
        </div>
      {:else}
        <div class="msg-list">
          {#each 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 dmMessages.length === 0 && activeDmAgentId}
            <div class="msg-empty">No messages yet</div>
          {/if}
          {#if !activeDmAgentId}
            <div class="msg-empty">Select an agent to message</div>
          {/if}
        </div>
      {/if}

      <!-- Feature 7: Channel member list toggle -->
      {#if mode === 'channels' && activeChannelId}
        <button class="members-toggle" onclick={() => showMembers = !showMembers}>
          Members ({channelMembers.length})
        </button>
        {#if showMembers}
          <div class="members-list">
            {#each 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={mode === 'channels' ? 'Message channel...' : 'Send DM...'}
          bind:value={input}
          onkeydown={handleKeydown}
        />
        <button class="msg-send-btn" onclick={sendMessage} disabled={!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>
