<script setup lang="ts">
import { computed, ref } from 'vue'
import { useElementSize } from '@vueuse/core'

import TimelineAxis from './TimelineAxis.vue'
import TimelineRow from './TimelineRow.vue'
import ZoomControls from './ZoomControls.vue'
import NodeHoverTooltipOverlay from '@/components/trace/NodeHoverTooltipOverlay.vue'
import { useNodeHoverTooltip } from '@/composables/useNodeHoverTooltip'
import { ScrollArea, ScrollBar } from '@/components/ui/scroll-area'
import { useTimelineData } from '@/composables/useTimelineData'
import { useTimelineLayout } from '@/composables/useTimelineLayout'
import { useUiStore } from '@/stores/uiStore'
import type { TimelineItem } from '@/types/timeline'
import type { TimelineNodeHoverPayload } from '@/types/traceTooltip'
import { toNodeTooltipData } from '@/utils/traceTooltip'
import { getAllAncestors } from '@/utils/treeTraversal'

const uiStore = useUiStore()

// container for dynamic sizing
const wrapper = ref<HTMLElement | null>(null)
const scrollArea = ref<InstanceType<typeof ScrollArea> | null>(null)
const { width } = useElementSize(wrapper)
const { height } = useElementSize(scrollArea)

// data and layout composables
const { data } = useTimelineData()
const { totalHeight, zoomedWidth, timeScale, ticks } = useTimelineLayout(data, width, height)
const { hoveredNodeInfo, setNodeHover, clearNodeHover } = useNodeHoverTooltip()

// selection logic
const ancestorIds = computed<Set<string>>(() => {
  if (!uiStore.selectedNodeId || !uiStore.selectedTrace?.parentNode) return new Set()

  const ancestors = getAllAncestors(uiStore.selectedTrace.parentNode, uiStore.selectedNodeId)

  return new Set(ancestors || [])
})

function isDimmed(item: TimelineItem): boolean {
  if (!uiStore.selectedNodeId) return false
  return item.id !== uiStore.selectedNodeId && !ancestorIds.value.has(item.id)
}

function toggleCollapse(id: string) {
  uiStore.toggleNodeCollapse(id)
}

function handleRowHover(payload: TimelineNodeHoverPayload) {
  setNodeHover(toNodeTooltipData(payload.item), payload.clientX, payload.clientY)
}
</script>

<template>
  <div
    ref="wrapper"
    class="h-full w-full overflow-hidden flex flex-col bg-background text-foreground relative"
  >
    <div class="flex justify-end">
      <ZoomControls class="p-2" />
    </div>

    <ScrollArea ref="scrollArea" class="flex-1 min-h-0 w-full">
      <!-- Main SVG Container -->
      <svg v-if="timeScale" :width="zoomedWidth" :height="totalHeight" class="block">
        <!-- X-Axis -->
        <TimelineAxis
          :ticks="ticks"
          :time-scale="timeScale"
          :zoomed-width="zoomedWidth"
          :total-height="totalHeight"
        />

        <!-- Timeline Rows -->
        <TimelineRow
          v-for="(item, index) in data"
          :key="item.id"
          :item="item"
          :index="index"
          :time-scale="timeScale"
          :zoomed-width="zoomedWidth"
          :is-selected="item.id === uiStore.selectedNodeId"
          :is-dimmed="isDimmed(item)"
          :is-collapsed="uiStore.collapsedNodeIds.has(item.id)"
          @toggle-collapse="toggleCollapse"
          @select-node="uiStore.toggleSelectNode"
          @hover-node="handleRowHover"
          @leave-node="clearNodeHover"
        />
      </svg>

      <ScrollBar orientation="horizontal" />
      <ScrollBar orientation="vertical" />
    </ScrollArea>

    <NodeHoverTooltipOverlay :info="hoveredNodeInfo" />
  </div>
</template>
