<script setup lang="ts">
import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'

type LifecycleEvent =
  | 'SessionStart' | 'UserPromptSubmit'
  | 'PreToolUse' | 'PermissionRequest' | 'PostToolUse' | 'PostToolUseFailure'
  | 'Notification' | 'SubagentStart' | 'SubagentStop'
  | 'Stop' | 'TeammateIdle' | 'TaskCompleted'
  | 'ConfigChange' | 'PreCompact' | 'SessionEnd'

type Category = 'session' | 'user' | 'tool' | 'agent' | 'system'

interface LifecycleInfo {
  color: string
  label: string
  category: Category
  processing?: boolean
}

const LIFECYCLE_DISPLAY: Record<LifecycleEvent, LifecycleInfo> = {
  SessionStart:       { color: '#60a5fa', label: 'Session started',     category: 'session' },
  UserPromptSubmit:   { color: '#a78bfa', label: 'Prompt submitted',    category: 'user' },
  PreToolUse:         { color: '#fbbf24', label: 'Tool starting',       category: 'tool',    processing: true },
  PermissionRequest:  { color: '#fb923c', label: 'Permission required', category: 'tool',    processing: true },
  PostToolUse:        { color: '#4ade80', label: 'Tool completed',      category: 'tool' },
  PostToolUseFailure: { color: '#f87171', label: 'Tool failed',         category: 'tool' },
  Notification:       { color: '#38bdf8', label: 'Notification',        category: 'system' },
  SubagentStart:      { color: '#c084fc', label: 'Subagent spawned',    category: 'agent',   processing: true },
  SubagentStop:       { color: '#a855f7', label: 'Subagent finished',   category: 'agent' },
  Stop:               { color: '#22d3ee', label: 'Response complete',   category: 'session' },
  TeammateIdle:       { color: '#94a3b8', label: 'Teammate idle',       category: 'agent' },
  TaskCompleted:      { color: '#34d399', label: 'Task completed',      category: 'system' },
  ConfigChange:       { color: '#e879f9', label: 'Config changed',      category: 'system' },
  PreCompact:         { color: '#f59e0b', label: 'Compacting context',  category: 'system',  processing: true },
  SessionEnd:         { color: '#6b7280', label: 'Session ended',       category: 'session' },
}

const CATEGORY_ORDER: Record<Category, number> = {
  session: 0, user: 1, tool: 2, agent: 3, system: 4
}

interface MockStep {
  event: LifecycleEvent
  duration: number
  detail?: string
}

const MOCK_SEQUENCE: MockStep[] = [
  { event: 'SessionStart',       duration: 2000,  detail: 'claude-opus-4-6' },
  { event: 'UserPromptSubmit',   duration: 1500,  detail: '"Fix the login bug"' },
  { event: 'PreToolUse',         duration: 800,   detail: 'Grep' },
  { event: 'PostToolUse',        duration: 1200,  detail: 'Grep' },
  { event: 'PreToolUse',         duration: 600,   detail: 'Read' },
  { event: 'PostToolUse',        duration: 1000,  detail: 'Read' },
  { event: 'PreToolUse',         duration: 500,   detail: 'Edit' },
  { event: 'PermissionRequest',  duration: 3000,  detail: 'Edit src/auth.ts' },
  { event: 'PostToolUse',        duration: 1500,  detail: 'Edit' },
  { event: 'PreToolUse',         duration: 400,   detail: 'Bash' },
  { event: 'PermissionRequest',  duration: 2500,  detail: 'npm test' },
  { event: 'PostToolUseFailure', duration: 2000,  detail: 'Bash (exit 1)' },
  { event: 'Notification',       duration: 1500,  detail: 'Test failed, retrying' },
  { event: 'PreToolUse',         duration: 500,   detail: 'Edit' },
  { event: 'PostToolUse',        duration: 1000,  detail: 'Edit' },
  { event: 'PreToolUse',         duration: 400,   detail: 'Bash' },
  { event: 'PostToolUse',        duration: 1500,  detail: 'Bash (tests pass)' },
  { event: 'SubagentStart',      duration: 1000,  detail: 'code-review' },
  { event: 'SubagentStop',       duration: 1500,  detail: 'code-review' },
  { event: 'PreCompact',         duration: 2000 },
  { event: 'TaskCompleted',      duration: 1500,  detail: 'Login bug fixed' },
  { event: 'Stop',               duration: 3000,  detail: 'Done' },
  { event: 'TeammateIdle',       duration: 1500 },
  { event: 'ConfigChange',       duration: 1200,  detail: '.claude/settings.json' },
  { event: 'SessionEnd',         duration: 4000 },
]

interface HookHistoryEntry {
  event: string
  timestamp: number
  detail?: string
}

interface EventCountEntry {
  event: LifecycleEvent
  count: number
  color: string
}

const props = defineProps<{
  currentEvent?: string | null
  eventDetail?: string
  hookHistory?: HookHistoryEntry[]
}>()

const isMock = computed(() => !props.currentEvent || !(props.currentEvent in LIFECYCLE_DISPLAY))

const mockIndex = ref(0)
const mockHistory = ref<{ event: string }[]>([])
let mockTimer: ReturnType<typeof setTimeout> | null = null

const activeEvent = computed<LifecycleEvent>(() => {
  if (!isMock.value) return props.currentEvent as LifecycleEvent
  return MOCK_SEQUENCE[mockIndex.value].event
})

const activeDetail = computed(() => {
  if (!isMock.value) return props.eventDetail || ''
  return MOCK_SEQUENCE[mockIndex.value].detail || ''
})

const displayInfo = computed(() => LIFECYCLE_DISPLAY[activeEvent.value])
const isProcessing = computed(() => !!displayInfo.value.processing)

// ── Badge counts ──

function countEvents(entries: { event: string }[]): EventCountEntry[] {
  const counts = new Map<string, number>()
  for (const entry of entries) {
    counts.set(entry.event, (counts.get(entry.event) || 0) + 1)
  }

  const result: EventCountEntry[] = []
  for (const [event, count] of counts) {
    if (event in LIFECYCLE_DISPLAY) {
      result.push({
        event: event as LifecycleEvent,
        count,
        color: LIFECYCLE_DISPLAY[event as LifecycleEvent].color,
      })
    }
  }

  result.sort((a, b) => {
    const ca = LIFECYCLE_DISPLAY[a.event].category
    const cb = LIFECYCLE_DISPLAY[b.event].category
    if (CATEGORY_ORDER[ca] !== CATEGORY_ORDER[cb]) {
      return CATEGORY_ORDER[ca] - CATEGORY_ORDER[cb]
    }
    return a.event.localeCompare(b.event)
  })

  return result
}

const realCounts = computed(() => countEvents(props.hookHistory || []))
const mockCounts = computed(() => countEvents(mockHistory.value))
const displayCounts = computed(() => isMock.value ? mockCounts.value : realCounts.value)

// ── Mock mode ──

function advanceMock() {
  const nextIndex = (mockIndex.value + 1) % MOCK_SEQUENCE.length
  const nextEvent = MOCK_SEQUENCE[nextIndex].event

  if (nextEvent === 'SessionStart') {
    mockHistory.value = []
  }

  mockHistory.value = [...mockHistory.value, { event: nextEvent }]
  mockIndex.value = nextIndex
  scheduleMock()
}

function scheduleMock() {
  if (mockTimer) clearTimeout(mockTimer)
  mockTimer = setTimeout(advanceMock, MOCK_SEQUENCE[mockIndex.value].duration)
}

watch(isMock, (mock) => {
  if (mock) {
    mockHistory.value = [{ event: MOCK_SEQUENCE[mockIndex.value].event }]
    scheduleMock()
  } else if (mockTimer) {
    clearTimeout(mockTimer)
    mockTimer = null
  }
})

onMounted(() => {
  if (isMock.value) {
    mockHistory.value = [{ event: MOCK_SEQUENCE[mockIndex.value].event }]
    scheduleMock()
  }
})

onBeforeUnmount(() => {
  if (mockTimer) {
    clearTimeout(mockTimer)
    mockTimer = null
  }
})
</script>

<template>
  <div class="lifecycle-ribbon" :class="['category-' + displayInfo.category]">
    <!-- Badge counts -->
    <div class="lc-badges" v-if="displayCounts.length > 0">
      <TransitionGroup name="badge">
        <span
          v-for="entry in displayCounts"
          :key="entry.event"
          class="lc-badge"
          :style="{
            background: entry.color + '1a',
            color: entry.color,
            borderColor: entry.color + '33',
          }"
          :title="entry.event + ': ' + entry.count"
        >{{ entry.count }}</span>
      </TransitionGroup>
    </div>

    <!-- Current event display -->
    <Transition name="lc" mode="out-in">
      <div class="lc-content" :key="activeEvent + activeDetail">
        <span
          class="lc-dot"
          :class="{ processing: isProcessing }"
          :style="{ background: displayInfo.color }"
        />
        <span class="lc-event" :style="{ color: displayInfo.color }">{{ activeEvent }}</span>
        <span v-if="activeDetail" class="lc-detail">{{ activeDetail }}</span>
      </div>
    </Transition>
  </div>
</template>

<style scoped>
.lifecycle-ribbon {
  display: flex;
  align-items: center;
  min-height: 20px;
  padding: 0.15rem 0.5rem;
  border-top: 1px solid rgba(255, 255, 255, 0.04);
  transition: border-top-color 0.3s ease;
}

.lifecycle-ribbon.category-session { border-top-color: rgba(96, 165, 250, 0.15); }
.lifecycle-ribbon.category-user    { border-top-color: rgba(167, 139, 250, 0.15); }
.lifecycle-ribbon.category-tool    { border-top-color: rgba(251, 191, 36, 0.15); }
.lifecycle-ribbon.category-agent   { border-top-color: rgba(192, 132, 252, 0.15); }
.lifecycle-ribbon.category-system  { border-top-color: rgba(56, 189, 248, 0.15); }

/* ── Badges ── */

.lc-badges {
  display: flex;
  align-items: center;
  gap: 2px;
  flex-shrink: 0;
  margin-right: 4px;
  overflow: hidden;
}

.lc-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 12px;
  height: 12px;
  padding: 0 2px;
  font-size: 8px;
  font-weight: 700;
  font-family: 'Courier New', monospace;
  border: 1px solid;
  border-radius: 2px;
  line-height: 1;
  white-space: nowrap;
}

.badge-enter-active {
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.badge-leave-active {
  transition: opacity 0.15s ease;
}

.badge-enter-from {
  opacity: 0;
  transform: scale(0.7);
}

.badge-leave-to {
  opacity: 0;
}

.badge-move {
  transition: transform 0.2s ease;
}

/* ── Current event ── */

.lc-content {
  display: flex;
  align-items: center;
  gap: 5px;
  flex: 1;
  min-width: 0;
}

.lc-dot {
  width: 5px;
  height: 5px;
  flex-shrink: 0;
  border-radius: 0;
  transition: background 0.3s ease;
}

.lc-dot.processing {
  animation: pulse-lifecycle 1.5s ease-in-out infinite;
}

@keyframes pulse-lifecycle {
  0%, 100% { opacity: 0.5; transform: scale(0.8); }
  50% { opacity: 1; transform: scale(1.2); }
}

.lc-event {
  font-size: 9px;
  font-weight: 600;
  font-family: 'Courier New', monospace;
  white-space: nowrap;
  transition: color 0.3s ease;
}

.lc-detail {
  font-size: 9px;
  font-family: 'Courier New', monospace;
  color: rgba(255, 255, 255, 0.3);
  white-space: nowrap;
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Transition classes */
.lc-enter-active {
  transition: opacity 0.15s ease, transform 0.15s ease;
}

.lc-leave-active {
  transition: opacity 0.1s ease;
}

.lc-enter-from {
  opacity: 0;
  transform: translateY(4px);
}

.lc-leave-to {
  opacity: 0;
}
</style>
