<script setup>
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
import { fetchGuides, createGuide as apiCreate, deleteGuide, cancelGuide as apiCancel, reworkGuide as apiRework, createBaustein as apiCreateBaustein, fetchProjects, deleteProject as apiDeleteProject } from './api.js'
import TopicSidebar from './components/TopicSidebar.vue'
import TopicDetail from './components/TopicDetail.vue'
import BausteineView from './components/BausteineView.vue'
import HelpChat from './components/HelpChat.vue'

const guides = ref([])
const projects = ref([])
const manualTopics = ref([])
const selectedTopic = ref(null)
const previewGuide = ref(null)
const showBausteine = ref(false)
const showHelp = ref(false)
const bausteineRefreshKey = ref(0)
const sidebarPinned = ref(localStorage.getItem('sidebarPinned') !== 'false')
const sidebarSticky = ref(false)
let pollTimer = null

function toggleSidebarPin() {
  sidebarPinned.value = !sidebarPinned.value
  localStorage.setItem('sidebarPinned', sidebarPinned.value ? 'true' : 'false')
  if (sidebarPinned.value) sidebarSticky.value = false
}

function clickHoverZone() {
  sidebarSticky.value = !sidebarSticky.value
}

function onSidebarLeave() {
  if (!sidebarPinned.value) sidebarSticky.value = false
}

const projectNames = computed(() => projects.value.map((p) => p.name))

const topics = computed(() => {
  const isProject = new Set(projectNames.value)
  const topicDates = {}
  for (const g of guides.value) {
    if (isProject.has(g.topic)) continue
    if (!topicDates[g.topic] || g.created_at > topicDates[g.topic]) {
      topicDates[g.topic] = g.created_at
    }
  }
  for (const t of manualTopics.value) {
    if (isProject.has(t)) continue
    if (!topicDates[t]) topicDates[t] = new Date().toISOString()
  }
  return Object.keys(topicDates).sort((a, b) => topicDates[b].localeCompare(topicDates[a]))
})

const isProjectSelected = computed(() => projectNames.value.includes(selectedTopic.value))

const doneByFormat = computed(() => {
  const map = {}
  for (const g of guides.value) {
    if (g.topic !== selectedTopic.value) continue
    if (g.status !== 'done') continue
    if (!map[g.format] || g.created_at > map[g.format].created_at) {
      map[g.format] = g
    }
  }
  return map
})

const latestByFormat = computed(() => {
  const map = {}
  for (const g of guides.value) {
    if (g.topic !== selectedTopic.value) continue
    if (!map[g.format] || g.created_at > map[g.format].created_at) {
      map[g.format] = g
    }
  }
  return map
})

const hasActiveGuides = computed(() =>
  guides.value.some((g) => g.status === 'queued' || g.status === 'generating'),
)

async function loadGuides() {
  try {
    guides.value = await fetchGuides()
  } catch (e) {
    console.error('Fehler beim Laden:', e)
  }
}

async function loadProjects() {
  try {
    projects.value = await fetchProjects()
  } catch (e) {
    console.error('Fehler beim Laden der Projekte:', e)
  }
}

const FORMAT_ORDER = ['OnePager', 'Cheatsheet', 'MiniGuide', 'Guide', 'EndGuide']

function autoPreview() {
  const map = doneByFormat.value
  for (const f of FORMAT_ORDER) {
    if (map[f]) {
      previewGuide.value = map[f]
      return
    }
  }
  previewGuide.value = null
}

function selectTopic(topic) {
  selectedTopic.value = topic
  previewGuide.value = null
  showBausteine.value = false
  showHelp.value = false
  nextTick(autoPreview)
}

function createTopic(topic) {
  if (!manualTopics.value.includes(topic)) {
    manualTopics.value.push(topic)
  }
  selectedTopic.value = topic
  previewGuide.value = null
  showHelp.value = false
}

function onHelpSelect(title) {
  createTopic(title)
}

async function handleFormatClick({ format, instructions, reindex }) {
  if (!selectedTopic.value) return
  await apiCreate(selectedTopic.value, format, instructions, reindex || false)
  await loadGuides()
  startPolling()
}

async function handleDeleteProject(name) {
  await apiDeleteProject(name)
  if (selectedTopic.value === name) {
    selectedTopic.value = null
    previewGuide.value = null
  }
  await loadProjects()
}

async function handleRework({ guideId, instructions }) {
  await apiRework(guideId, instructions)
  await loadGuides()
  startPolling()
}

function handlePreview(guide) {
  previewGuide.value = guide
  showBausteine.value = false
}

function handleShowBausteine() {
  showBausteine.value = true
  previewGuide.value = null
}

async function handleSidebarAddBaustein(title) {
  if (!selectedTopic.value) return
  await apiCreateBaustein(selectedTopic.value, title)
  bausteineRefreshKey.value++
}

async function handleDeleteGuide(guideId) {
  await deleteGuide(guideId)
  if (previewGuide.value?.id === guideId) {
    previewGuide.value = null
  }
  await loadGuides()
}

function startPolling() {
  stopPolling()
  pollTimer = setInterval(async () => {
    await loadGuides()
    if (!hasActiveGuides.value) stopPolling()
  }, 3000)
}

function stopPolling() {
  if (pollTimer) {
    clearInterval(pollTimer)
    pollTimer = null
  }
}

async function handleCancel(guideId) {
  await apiCancel(guideId)
  await loadGuides()
}

async function handleDeleteTopic(topic) {
  const topicGuides = guides.value.filter((g) => g.topic === topic)
  for (const g of topicGuides) {
    await deleteGuide(g.id)
  }
  manualTopics.value = manualTopics.value.filter((t) => t !== topic)
  if (selectedTopic.value === topic) {
    selectedTopic.value = null
    previewGuide.value = null
  }
  await loadGuides()
}

function onVisibility() {
  if (document.hidden) {
    stopPolling()
  } else {
    loadGuides()
    if (hasActiveGuides.value) startPolling()
  }
}

onMounted(async () => {
  await Promise.all([loadGuides(), loadProjects()])
  if (!selectedTopic.value && topics.value.length) {
    selectTopic(topics.value[0])
  }
  document.addEventListener('visibilitychange', onVisibility)
})

onUnmounted(() => {
  stopPolling()
  document.removeEventListener('visibilitychange', onVisibility)
})
</script>

<template>
  <div class="layout" :class="{ 'sidebar-floating': !sidebarPinned, 'sidebar-open': sidebarSticky }">
    <div v-if="!sidebarPinned" class="hover-zone" @click="clickHoverZone"></div>
    <TopicSidebar
      :topics="topics"
      :projects="projectNames"
      :isProjectSelected="isProjectSelected"
      :selectedTopic="selectedTopic"
      :doneByFormat="doneByFormat"
      :latestByFormat="latestByFormat"
      :allGuides="guides"
      :bausteineActive="showBausteine"
      :pinned="sidebarPinned"
      @select="selectTopic"
      @create="createTopic"
      @formatClick="handleFormatClick"
      @deleteTopic="handleDeleteTopic"
      @deleteProject="handleDeleteProject"
      @cancelGuide="handleCancel"
      @deleteGuide="handleDeleteGuide"
      @preview="handlePreview"
      @rework="handleRework"
      @showBausteine="handleShowBausteine"
      @addBaustein="handleSidebarAddBaustein"
      @togglePin="toggleSidebarPin"
      @sidebarLeave="onSidebarLeave"
      @openHelp="showHelp = true"
    />
    <HelpChat
      v-if="showHelp"
      @close="showHelp = false"
      @selectTopic="onHelpSelect"
    />
    <BausteineView
      v-else-if="selectedTopic && showBausteine"
      :topic="selectedTopic"
      :refreshKey="bausteineRefreshKey"
    />
    <TopicDetail
      v-else-if="selectedTopic"
      :previewGuide="previewGuide"
    />
    <div v-else class="empty-main">
      <p>Thema in der Sidebar anlegen oder auswählen.</p>
    </div>
  </div>
</template>

<style>
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: -apple-system, 'Segoe UI', Roboto, sans-serif;
  background: #f8f9fb;
  color: #1a1a1a;
}

.layout {
  display: flex;
  height: 100vh;
  overflow: hidden;
  position: relative;
}

.hover-zone {
  position: fixed;
  left: 0;
  top: 0;
  width: 50px;
  height: 100vh;
  z-index: 5;
  cursor: pointer;
}

.layout.sidebar-floating > .sidebar {
  position: fixed;
  left: 0;
  top: 0;
  height: 100vh;
  transform: translateX(-100%);
  transition: transform 0.2s ease;
  z-index: 10;
  box-shadow: 0 0 16px rgba(0, 0, 0, 0.12);
}

.layout.sidebar-floating .hover-zone:hover ~ .sidebar,
.layout.sidebar-floating > .sidebar:hover,
.layout.sidebar-floating.sidebar-open > .sidebar {
  transform: translateX(0);
}

.empty-main {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #5a6470;
  font-size: 1rem;
}
</style>
