<script setup lang="ts">
import { ref, computed, nextTick, onMounted, onUnmounted, watch } from 'vue';
import { useChatStore } from '@/stores/chat';
import ChatPanel from '@/components/ChatPanel.vue';
import ChatInputBar from '@/components/ChatInputBar.vue';

const props = defineProps<{ projectId: number }>();

const emit = defineEmits<{
  'note-changed': [noteId: number];
  'task-changed': [];
}>();

const chatStore = useChatStore();

// SSE watcher — emit refresh events when tool calls succeed during streaming
const processedCount = ref(0);

watch(
  () => chatStore.streamingToolCalls,
  (calls) => {
    for (let i = processedCount.value; i < calls.length; i++) {
      const tc = calls[i];
      if (tc.status !== 'success') continue;

      // Note-editor refresh: any successful create_note/update_note
      if (['create_note', 'update_note'].includes(tc.function) && tc.result?.data?.id) {
        emit('note-changed', tc.result.data.id as number);
      }

      // Task-panel refresh: milestone changes, or note changes where the note is a task (has status)
      const isTaskNoteChange =
        ['create_note', 'update_note'].includes(tc.function) &&
        tc.result?.data?.status !== undefined;
      const isMilestoneChange = ['create_milestone', 'update_milestone'].includes(tc.function);
      if (isTaskNoteChange || isMilestoneChange) {
        emit('task-changed');
      }
    }
    processedCount.value = calls.length;
  },
  { deep: true }
);

watch(
  () => chatStore.streaming,
  (s) => {
    if (!s) processedCount.value = 0;
  }
);

type WidgetState = 'collapsed' | 'expanded';
const widgetState = ref<WidgetState>('collapsed');

const chatPanelRef = ref<InstanceType<typeof ChatPanel> | null>(null);
const inputBarRef = ref<InstanceType<typeof ChatInputBar> | null>(null);

const workspaceConvId = ref<number | null>(null);
let isNewConv = false;

const historyOpen = ref(false);

const projectConversations = computed(() =>
  chatStore.conversations
    .filter((c) => c.rag_project_id === props.projectId)
    .slice()
    .sort((a, b) => (b.updated_at || '').localeCompare(a.updated_at || ''))
);

async function pickConversation(convId: number) {
  historyOpen.value = false;
  if (convId === workspaceConvId.value) return;
  await chatStore.fetchConversation(convId);
  workspaceConvId.value = convId;
  // The picked conversation already exists on the server; not ours to clean up.
  isNewConv = false;
  localStorage.setItem(_storageKey(props.projectId), String(convId));
}

function toggleHistory() {
  historyOpen.value = !historyOpen.value;
}

function conversationLabel(c: { id: number; title?: string | null }): string {
  return (c.title && c.title.trim()) || `Conversation #${c.id}`;
}

function _storageKey(pid: number) {
  return `workspace_conv_${pid}`;
}

function expand() {
  widgetState.value = 'expanded';
  nextTick(() => chatPanelRef.value?.focus());
}
function collapse() {
  widgetState.value = 'collapsed';
  nextTick(() => inputBarRef.value?.focus());
}

async function restart() {
  const conv = await chatStore.createConversation();
  workspaceConvId.value = conv.id;
  isNewConv = true;
  localStorage.setItem(_storageKey(props.projectId), String(conv.id));
  await chatStore.fetchConversation(conv.id);
}

/** Auto-expand and send — used when user submits from collapsed input. */
async function onCollapsedSubmit(payload: { content: string; contextNoteId?: number }) {
  widgetState.value = 'expanded';
  await chatStore.sendMessage(payload.content, payload.contextNoteId, undefined, false);
}

function prefill(text: string) {
  if (widgetState.value === 'expanded') {
    chatPanelRef.value?.prefill(text);
  } else {
    inputBarRef.value?.prefill(text);
  }
}

onMounted(async () => {
  if (chatStore.conversations.length === 0) {
    await chatStore.fetchConversations();
  }

  const key = _storageKey(props.projectId);
  const storedId = localStorage.getItem(key);

  if (storedId) {
    const existingId = Number(storedId);
    try {
      await chatStore.fetchConversation(existingId);
      workspaceConvId.value = existingId;
      isNewConv = false;
      chatStore.reconnectIfGenerating(existingId);
    } catch {
      localStorage.removeItem(key);
    }
  }

  if (workspaceConvId.value === null) {
    const conv = await chatStore.createConversation();
    workspaceConvId.value = conv.id;
    isNewConv = true;
    await chatStore.fetchConversation(conv.id);
    localStorage.setItem(key, String(conv.id));
  }
});

onUnmounted(async () => {
  if (workspaceConvId.value !== null && isNewConv) {
    const id = workspaceConvId.value;
    const conv = chatStore.conversations.find((c) => c.id === id);
    if (conv && conv.message_count === 0) {
      await chatStore.deleteConversation(id);
      localStorage.removeItem(_storageKey(props.projectId));
    }
  }
});

defineExpose({ prefill });
</script>

<template>
  <!-- Bottom-anchored chat dock: collapsed (input only) or expanded (full panel) -->
  <div
    class="ws-chat-widget"
    :class="{ 'ws-chat-widget--expanded': widgetState === 'expanded' }"
  >
    <!-- Header (expanded only) -->
    <div v-if="widgetState === 'expanded'" class="ws-chat-header">
      <span class="ws-chat-title">Project chat</span>
      <div class="ws-chat-header-actions">
        <div class="ws-chat-history-wrap">
          <button
            class="btn-icon-sm"
            :class="{ active: historyOpen }"
            title="History"
            @click="toggleHistory"
          >▾</button>
          <div v-if="historyOpen" class="ws-chat-history-menu">
            <div v-if="projectConversations.length === 0" class="ws-chat-history-empty">
              No past conversations
            </div>
            <button
              v-for="c in projectConversations"
              :key="c.id"
              class="ws-chat-history-item"
              :class="{ current: c.id === workspaceConvId }"
              @click="pickConversation(c.id)"
            >
              <span class="ws-chat-history-title">{{ conversationLabel(c) }}</span>
            </button>
          </div>
        </div>
        <button class="btn-icon-sm" title="Restart conversation" @click="restart">↻</button>
        <button class="btn-icon-sm" title="Collapse" @click="collapse">
          <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
            <polyline points="6 9 12 15 18 9"/>
          </svg>
        </button>
      </div>
    </div>

    <!-- Expanded body: full ChatPanel (includes its own input bar) -->
    <div v-if="widgetState === 'expanded'" class="ws-chat-body">
      <ChatPanel
        ref="chatPanelRef"
        variant="full"
        :projectId="projectId"
        placeholder="Message the agent…"
      />
    </div>

    <!-- Collapsed: standalone input bar with expand affordance -->
    <div v-else class="ws-chat-collapsed">
      <button class="ws-chat-expand-btn" title="Expand chat" @click="expand">
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
          <polyline points="18 15 12 9 6 15"/>
        </svg>
      </button>
      <div class="ws-chat-input-row">
        <ChatInputBar
          ref="inputBarRef"
          placeholder="Message the agent…"
          @submit="onCollapsedSubmit"
          @abort="chatStore.cancelGeneration()"
        />
      </div>
    </div>
  </div>
</template>

<style scoped>
.ws-chat-widget {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  max-width: var(--page-max-width);
  margin-inline: auto;
  z-index: 20;
  display: flex;
  flex-direction: column;
  background: var(--color-bg-secondary);
  border-radius: 16px 16px 0 0;
  box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.35), 0 -1px 0 rgba(255, 255, 255, 0.05);
  overflow: hidden;
  transition: height 0.2s ease;
}
.ws-chat-widget--expanded {
  height: 500px;
}

.ws-chat-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 14px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  flex-shrink: 0;
}
.ws-chat-title {
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
}
.ws-chat-header-actions {
  display: flex;
  gap: 4px;
  align-items: center;
}
.btn-icon-sm {
  background: none;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  padding: 2px 6px;
  font-size: 0.9rem;
  line-height: 1;
  border-radius: 4px;
}
.btn-icon-sm:hover:not(:disabled) {
  color: var(--color-text);
  background: color-mix(in srgb, var(--color-primary) 10%, transparent);
}
.btn-icon-sm:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.btn-icon-sm.active {
  color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 12%, transparent);
}

.ws-chat-history-wrap {
  position: relative;
}
.ws-chat-history-menu {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 4px;
  min-width: 220px;
  max-height: 260px;
  overflow-y: auto;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  z-index: 30;
  padding: 4px;
}
.ws-chat-history-empty {
  padding: 10px 12px;
  font-size: 0.82rem;
  color: var(--color-text-muted);
  text-align: center;
}
.ws-chat-history-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: 8px 10px;
  border-radius: 6px;
  color: var(--color-text);
  font-size: 0.85rem;
  cursor: pointer;
  font-family: inherit;
}
.ws-chat-history-item:hover {
  background: color-mix(in srgb, var(--color-primary) 10%, transparent);
}
.ws-chat-history-item.current {
  color: var(--color-primary);
  font-weight: 600;
}
.ws-chat-history-title {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ws-chat-body {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.ws-chat-body :deep(.chat-body) {
  flex: 1;
  min-height: 0;
}

.ws-chat-collapsed {
  display: flex;
  align-items: stretch;
}
.ws-chat-expand-btn {
  flex-shrink: 0;
  padding: 0 10px;
  background: none;
  border: none;
  border-right: 1px solid var(--color-border);
  color: var(--color-text-muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ws-chat-expand-btn:hover {
  color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 8%, transparent);
}

.ws-chat-input-row {
  flex: 1;
  min-width: 0;
  padding: 10px 12px;
  flex-shrink: 0;
}
</style>
