<script setup lang="ts">
import { computed } from 'vue'
import type { ParsedAssistantMessage } from '@/types/transcript-debug'
import ThinkingBlock from './ThinkingBlock.vue'
import ToolCallBlock from './ToolCallBlock.vue'
import MarkdownContent from './MarkdownContent.vue'
import AskUserQuestionCard from './toolCards/AskUserQuestionCard.vue'
import ExitPlanModeCard from './toolCards/ExitPlanModeCard.vue'
import EnterPlanModeCard from './toolCards/EnterPlanModeCard.vue'
import ReadCard from './toolCards/ReadCard.vue'
import WriteCard from './toolCards/WriteCard.vue'
import BashCard from './toolCards/BashCard.vue'
import EditCard from './toolCards/EditCard.vue'
import GrepCard from './toolCards/GrepCard.vue'
import GlobCard from './toolCards/GlobCard.vue'
import TaskCard from './toolCards/TaskCard.vue'

const TASK_TOOLS = new Set(['Task', 'TaskCreate', 'TaskUpdate', 'TaskGet', 'TaskList'])

const props = defineProps<{
  message: ParsedAssistantMessage
  showHeader?: boolean
}>()

// Filter out empty text blocks (streaming placeholders)
const visibleTextBlocks = computed(() =>
  props.message.textBlocks.filter(t => t.trim().length > 0)
)

// Show thinking animation when assistant has no real content yet
const isStreaming = computed(() =>
  visibleTextBlocks.value.length === 0 &&
  props.message.thinkingBlocks.length === 0 &&
  props.message.toolCalls.length === 0 &&
  !props.message.stopReason
)

function formatTime(ts: string): string {
  if (!ts) return ''
  return new Date(ts).toLocaleTimeString()
}

function formatTokens(n?: number): string {
  if (!n) return '0'
  if (n >= 1000) return `${(n / 1000).toFixed(1)}k`
  return String(n)
}
</script>

<template>
  <div :class="['assistant-bubble', { continuation: showHeader === false }]">
    <div v-if="showHeader !== false" class="bubble-header">
      <span class="role-badge">Assistant</span>
      <span class="model-badge">{{ message.model }}</span>
      <span v-if="message.usage" class="token-info">
        {{ formatTokens(message.usage.input_tokens) }}in / {{ formatTokens(message.usage.output_tokens) }}out
      </span>
      <span v-if="message.stopReason" class="stop-reason">{{ message.stopReason }}</span>
      <span class="timestamp">{{ formatTime(message.timestamp) }}</span>
    </div>

    <!-- Streaming/thinking animation -->
    <div v-if="isStreaming" class="thinking-animation">
      <div class="thinking-dots">
        <span class="dot"></span>
        <span class="dot"></span>
        <span class="dot"></span>
      </div>
      <span class="thinking-label">Thinking...</span>
    </div>

    <!-- Thinking blocks -->
    <ThinkingBlock
      v-for="(t, i) in message.thinkingBlocks"
      :key="'think-' + i"
      :content="t"
    />

    <!-- Text content (filtered, markdown-rendered) -->
    <MarkdownContent
      v-for="(text, i) in visibleTextBlocks"
      :key="'text-' + i"
      :content="text"
    />

    <!-- Tool calls -->
    <template v-for="tc in message.toolCalls" :key="tc.id">
      <AskUserQuestionCard v-if="tc.name === 'AskUserQuestion'" :call="tc" />
      <ExitPlanModeCard v-else-if="tc.name === 'ExitPlanMode'" :call="tc" />
      <EnterPlanModeCard v-else-if="tc.name === 'EnterPlanMode'" :call="tc" />
      <ReadCard v-else-if="tc.name === 'Read'" :call="tc" />
      <WriteCard v-else-if="tc.name === 'Write'" :call="tc" />
      <BashCard v-else-if="tc.name === 'Bash'" :call="tc" />
      <EditCard v-else-if="tc.name === 'Edit'" :call="tc" />
      <GrepCard v-else-if="tc.name === 'Grep'" :call="tc" />
      <GlobCard v-else-if="tc.name === 'Glob'" :call="tc" />
      <TaskCard v-else-if="TASK_TOOLS.has(tc.name)" :call="tc" />
      <ToolCallBlock v-else :call="tc" />
    </template>
  </div>
</template>

<style scoped>
.assistant-bubble {
  background: transparent;
  border: none;
  border-radius: 0;
  padding: 0.5rem 0.25rem;
}

.assistant-bubble.continuation {
  padding-top: 0;
}

.bubble-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
  flex-wrap: wrap;
}

.role-badge {
  font-size: 11px;
  font-weight: 600;
  color: #22c55e;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.model-badge {
  font-size: 10px;
  padding: 0.1rem 0.4rem;
  border-radius: 4px;
  background: rgba(99, 102, 241, 0.1);
  color: var(--accent, #6366f1);
  font-family: 'SF Mono', 'Fira Code', monospace;
}

.token-info {
  font-size: 10px;
  color: var(--text-muted);
  font-family: 'SF Mono', 'Fira Code', monospace;
}

.stop-reason {
  font-size: 10px;
  padding: 0.1rem 0.4rem;
  border-radius: 4px;
  background: var(--bg-hover);
  color: var(--text-muted);
}

.timestamp {
  font-size: 11px;
  color: var(--text-muted);
  margin-left: auto;
  font-family: 'SF Mono', 'Fira Code', monospace;
}

/* Thinking animation */
.thinking-animation {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0;
}

.thinking-dots {
  display: flex;
  gap: 4px;
}

.dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #22c55e;
  opacity: 0.4;
  animation: pulse-dot 1.4s ease-in-out infinite;
}

.dot:nth-child(2) {
  animation-delay: 0.2s;
}

.dot:nth-child(3) {
  animation-delay: 0.4s;
}

@keyframes pulse-dot {
  0%, 80%, 100% {
    opacity: 0.2;
    transform: scale(0.8);
  }
  40% {
    opacity: 1;
    transform: scale(1.1);
  }
}

.thinking-label {
  font-size: 12px;
  color: var(--text-muted);
  font-style: italic;
}

.text-content {
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-primary);
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0.25rem 0;
}
</style>
