<script setup lang="ts">
import { ref, watch, onUnmounted } from 'vue'
import { api, type PipelineLog } from '../api'

const props = defineProps<{
  pipelineId: string
  pipelineStatus: string
}>()

const visible = ref(false)
const logs = ref<PipelineLog[]>([])
const error = ref('')
const consoleEl = ref<HTMLElement | null>(null)
let sinceId = 0
let userScrolled = false
let timer: ReturnType<typeof setInterval> | null = null

const MAX_LOGS = 500

function levelClass(level: PipelineLog['level']): string {
  switch (level) {
    case 'INFO': return 'text-gray-300'
    case 'DEBUG': return 'text-gray-500'
    case 'ERROR': return 'text-red-400'
    case 'WARN': return 'text-yellow-400'
  }
}

function onScroll() {
  if (!consoleEl.value) return
  const { scrollTop, clientHeight, scrollHeight } = consoleEl.value
  userScrolled = scrollTop + clientHeight < scrollHeight - 50
}

function scrollToBottom() {
  if (!consoleEl.value || userScrolled) return
  consoleEl.value.scrollTop = consoleEl.value.scrollHeight
}

async function fetchLogs() {
  try {
    const newLogs = await api.getPipelineLogs(props.pipelineId, sinceId)
    if (!newLogs.length) return
    sinceId = Math.max(...newLogs.map(l => l.id))
    logs.value = [...logs.value, ...newLogs].slice(-MAX_LOGS)
    // Scroll after DOM update
    setTimeout(scrollToBottom, 0)
  } catch (e: any) {
    error.value = e.message
  }
}

function startPolling() {
  if (timer) return
  timer = setInterval(async () => {
    await fetchLogs()
    if (props.pipelineStatus !== 'running' && props.pipelineStatus !== 'in_progress') {
      stopPolling()
    }
  }, 2000)
}

function stopPolling() {
  if (timer) { clearInterval(timer); timer = null }
}

async function toggle() {
  visible.value = !visible.value
  if (visible.value) {
    // Reset on open
    userScrolled = false
    await fetchLogs()
    if (props.pipelineStatus === 'running' || props.pipelineStatus === 'in_progress') {
      startPolling()
    }
  } else {
    stopPolling()
  }
}

// When status changes while panel is open — do final fetch and stop
watch(() => props.pipelineStatus, async (newStatus) => {
  if (!visible.value) return
  if (newStatus !== 'running' && newStatus !== 'in_progress') {
    stopPolling()
    await fetchLogs()
  } else {
    startPolling()
  }
})

onUnmounted(() => {
  stopPolling()
})
</script>

<template>
  <div class="mt-4">
    <button
      @click="toggle"
      class="text-xs text-gray-500 hover:text-gray-300 border border-gray-800 rounded px-3 py-1.5 bg-gray-900/50 hover:bg-gray-900 transition-colors"
    >
      {{ visible ? '▲ Скрыть лог' : '▼ Показать лог' }}
    </button>

    <div v-show="visible" class="mt-2 bg-gray-950 border border-gray-800 rounded-lg p-4 font-mono text-xs max-h-[400px] overflow-y-auto" ref="consoleEl" @scroll="onScroll">
      <div v-if="!logs.length && !error" class="text-gray-600">Нет записей...</div>
      <div v-if="error" class="text-red-400">Ошибка: {{ error }}</div>
      <div v-for="log in logs" :key="log.id" class="mb-1">
        <span class="text-gray-600">{{ log.ts }}</span>
        <span :class="[levelClass(log.level), 'ml-2 font-semibold']">[{{ log.level }}]</span>
        <span :class="[levelClass(log.level), 'ml-2']">{{ log.message }}</span>
        <pre v-if="log.extra_json" class="mt-0.5 ml-4 text-gray-500 whitespace-pre-wrap">{{ JSON.stringify(log.extra_json, null, 2) }}</pre>
      </div>
    </div>
  </div>
</template>
