<script setup>
import { computed, ref, watch, nextTick, onMounted, onUnmounted } from 'vue'
import { fetchGuideContent, chatGuide, fetchProgress, setProgress } from '../api.js'
import { renderMarkdown } from '../markdown.js'

const props = defineProps({
  previewGuide: { type: Object, default: null },
  dark: { type: Boolean, default: false },
  provider: { type: String, default: 'claude' },
  elementsOpen: { type: Boolean, default: false }, // Element-Sidebar offen → Chat nach links
})

const emit = defineEmits(['progressChanged', 'openElements'])

const isOnePager = computed(() => props.previewGuide?.format === 'OnePager')

// Rotierende Kapitel-Akzentfarben (passend zum OnePager-Cheat-Sheet, ohne Rot)
const CH_COLORS = ['#3b82f6', '#8b5cf6', '#14b8a6', '#f59e0b', '#22c55e', '#6366f1']

// --- Inhalt laden ---
const content = ref(null)
const loadError = ref(null)
const doneChapters = ref(new Set())
const scrollEl = ref(null)

watch(() => props.previewGuide?.id, loadContent, { immediate: true })

async function loadContent() {
  content.value = null
  loadError.value = null
  doneChapters.value = new Set()
  const g = props.previewGuide
  if (!g || g.status !== 'done') return
  try {
    content.value = await fetchGuideContent(g.id)
  } catch (e) {
    console.error('Fehler beim Laden des Guides:', e)
    loadError.value = 'Inhalt nicht verfügbar — die Datei fehlt. Guide neu generieren (▶).'
    return
  }
  try {
    const res = await fetchProgress(g.id)
    doneChapters.value = new Set(res.chapters || [])
  } catch { /* offline → leer */ }
  nextTick(scrollToFirstOpen)
}

// Zum ersten noch offenen Kapitel springen — aber nur, wenn schon etwas erledigt ist.
function scrollToFirstOpen() {
  if (!doneChapters.value.size || !content.value) return
  const chapters = Array.from(scrollEl.value?.querySelectorAll('section.chapter') || [])
  const firstOpen = chapters.find((el) => !el.classList.contains('ch-complete'))
  if (firstOpen && firstOpen !== chapters[0]) firstOpen.scrollIntoView({ block: 'start' })
}

// --- Kapitel-Fortschritt ---
async function toggleChapter(title) {
  const newState = !doneChapters.value.has(title)
  const optimistic = new Set(doneChapters.value)
  if (newState) optimistic.add(title)
  else optimistic.delete(title)
  doneChapters.value = optimistic
  try {
    const res = await setProgress(props.previewGuide.id, title, newState)
    doneChapters.value = new Set(res.chapters || [])
    emit('progressChanged')
  } catch {
    const rollback = new Set(doneChapters.value)
    if (newState) rollback.delete(title)
    else rollback.add(title)
    doneChapters.value = rollback
  }
}

// --- Chat ---
const chatOpen = ref(false)
const messages = ref([])
const input = ref('')
const loading = ref(false)
const messagesEl = ref(null)
const inputEl = ref(null)
const panelEl = ref(null)

function openChat() {
  chatOpen.value = true
  nextTick(() => inputEl.value?.focus())
}

function closeChat() {
  chatOpen.value = false
  messages.value = []
  input.value = ''
}

function onDocMouseDown(e) {
  if (!chatOpen.value) return
  if (panelEl.value && panelEl.value.contains(e.target)) return
  closeChat()
}

// Enter öffnet den Chat (wenn zu, nicht in Eingabefeld); ESC schließt ihn
function onDocKeyDown(e) {
  if (e.key === 'Escape' && chatOpen.value) {
    e.preventDefault()
    closeChat()
    return
  }
  if (e.key !== 'Enter' || chatOpen.value || !props.previewGuide) return
  const tag = document.activeElement?.tagName
  if (tag === 'INPUT' || tag === 'TEXTAREA') return
  e.preventDefault()
  openChat()
}

onMounted(() => {
  document.addEventListener('mousedown', onDocMouseDown, true)
  document.addEventListener('keydown', onDocKeyDown)
})
onUnmounted(() => {
  document.removeEventListener('mousedown', onDocMouseDown, true)
  document.removeEventListener('keydown', onDocKeyDown)
})

function extractContext() {
  if (!content.value) return { section: '', outline: '' }
  const outline = content.value.chapters
    .map((ch) => [ch.title, ...ch.sections.map((s) => '  ' + s.title)].join('\n'))
    .join('\n')
    .slice(0, 7000)

  // Aktuelle Section = letzte Karte, deren Oberkante oben im Viewport oder darüber liegt
  let section = ''
  const cards = Array.from(scrollEl.value?.querySelectorAll('.section-card') || [])
  let current = null
  for (const el of cards) {
    if (el.getBoundingClientRect().top <= 120) current = el
    else break
  }
  if (!current && cards.length) current = cards[0]
  if (current) section = current.innerText.trim().slice(0, 18000)
  return { section, outline }
}

async function scrollToBottom() {
  await nextTick()
  if (messagesEl.value) messagesEl.value.scrollTop = messagesEl.value.scrollHeight
}

async function send() {
  const text = input.value.trim()
  if (!text || loading.value || !props.previewGuide) return
  messages.value.push({ role: 'user', content: text })
  input.value = ''
  loading.value = true
  scrollToBottom()
  try {
    const { section, outline } = extractContext()
    const res = await chatGuide(props.previewGuide.id, {
      section,
      outline,
      messages: messages.value,
      provider: props.provider,
    })
    messages.value.push({ role: 'assistant', content: res.reply || '…' })
  } catch {
    messages.value.push({ role: 'assistant', content: 'Fehler bei der Anfrage.' })
  } finally {
    loading.value = false
    scrollToBottom()
    nextTick(() => inputEl.value?.focus())
  }
}
</script>

<template>
  <div class="detail">
    <div v-if="previewGuide && content" ref="scrollEl" class="guide-scroll">
      <div class="guide-content" :class="{ onepager: isOnePager }">
        <header class="guide-head">
          <h1>{{ previewGuide.topic }}</h1>
          <span class="guide-format">{{ previewGuide.format }}</span>
        </header>
        <section
          v-for="(ch, ci) in content.chapters"
          :key="ch.title"
          class="chapter"
          :class="{ 'ch-complete': doneChapters.has(ch.title) }"
          :style="{ '--ch-accent': CH_COLORS[ci % CH_COLORS.length] }"
        >
          <h2 class="chapter-title"><span class="ch-num">{{ ci + 1 }}</span>{{ ch.title }}</h2>
          <div class="sections">
            <article
              v-for="s in ch.sections"
              :key="s.num"
              :class="['section-card', isOnePager && s.key ? 'op-card op-' + s.key : '']"
              :style="isOnePager && s.key ? { gridArea: s.key } : null"
            >
              <h3>{{ s.title }}</h3>
              <div class="section-body markdown" v-html="renderMarkdown(s.md)"></div>
            </article>
          </div>
          <button
            v-if="!isOnePager"
            class="ch-toggle"
            :class="{ 'is-done': doneChapters.has(ch.title) }"
            @click="toggleChapter(ch.title)"
          >{{ doneChapters.has(ch.title) ? '✓ Erledigt – rückgängig' : 'Kapitel als erledigt markieren' }}</button>
        </section>
      </div>
    </div>

    <div v-else-if="previewGuide" class="empty-preview">
      <p>{{ loadError || 'Lade Inhalt…' }}</p>
    </div>

    <div class="empty-preview" v-else>
      <p>Guide-Format anklicken um zu generieren oder Vorschau zu öffnen.</p>
    </div>

    <button v-if="previewGuide && !chatOpen" class="chat-fab" :class="{ shifted: elementsOpen }" title="Fragen zum Guide" @click="openChat">💬</button>
    <button v-if="previewGuide && !chatOpen && !elementsOpen" class="chat-fab elements-fab" title="Elemente öffnen" @click="emit('openElements')">🗂</button>

    <div v-if="previewGuide && chatOpen" ref="panelEl" class="chat-panel" :class="{ shifted: elementsOpen }">
      <header class="chat-header">
        <span>Fragen zum Guide</span>
        <button class="chat-close" title="Chat beenden" @click="closeChat">×</button>
      </header>
      <div ref="messagesEl" class="chat-messages">
        <p v-if="!messages.length" class="chat-hint">Stell eine Frage zum aktuellen Abschnitt.</p>
        <template v-for="(m, i) in messages" :key="i">
          <div v-if="m.role === 'assistant'" class="chat-msg assistant markdown" v-html="renderMarkdown(m.content)"></div>
          <div v-else class="chat-msg user">{{ m.content }}</div>
        </template>
        <div v-if="loading" class="chat-msg assistant chat-typing">Denkt…</div>
      </div>
      <div class="chat-input">
        <textarea
          ref="inputEl"
          v-model="input"
          placeholder="Frage stellen…"
          @keydown.enter.exact.prevent="send"
        ></textarea>
        <button :disabled="!input.trim() || loading" @click="send">➤</button>
      </div>
    </div>
  </div>
</template>

<style scoped>
.detail {
  flex: 1;
  /* Flex-Item darf schmaler werden als seine Code-Blöcke — sonst sprengt
     deren Mindestbreite auf Mobile das Layout */
  min-width: 0;
  height: 100vh;
  position: relative;
}

.guide-scroll {
  height: 100%;
  overflow-y: auto;
  /* Kein horizontales Pannen der ganzen Seite — Code-Blöcke scrollen intern */
  overflow-x: hidden;
  background: var(--bg-preview);
}

.guide-content {
  max-width: 880px;
  margin: 0 auto;
  padding: 2rem 2.5rem 5rem;
  /* Lese-Zoom nur für den Inhalt — Sidebar/Chat bleiben unverändert */
  zoom: 1.2;
}

@media (max-width: 600px) {
  .guide-content {
    padding: 1.25rem 0.9rem 4rem;
  }
}

.guide-head {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  margin-bottom: 1.5rem;

  h1 {
    font-size: 1.7rem;
  }
}

.guide-format {
  color: var(--text-faint);
  font-size: 0.9rem;
  font-weight: 600;
}

.chapter {
  margin-bottom: 2.5rem;
}

.chapter-title {
  font-size: 1.25rem;
  margin-bottom: 0.9rem;
  padding-bottom: 0.4rem;
  border-bottom: 2px solid color-mix(in srgb, var(--ch-accent, var(--accent)) 35%, transparent);
  display: flex;
  align-items: center;
  gap: 10px;
}

.ch-num {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  background: var(--ch-accent, var(--accent));
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.85rem;
  font-weight: 700;
}

.chapter.ch-complete .sections {
  opacity: 0.4;
}

.section-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1rem 1.25rem;
  margin-bottom: 0.75rem;
}

/* Guides: Karten tragen die Kapitel-Akzentfarbe (OnePager hat eigene op-card-Farben) */
.guide-content:not(.onepager) .section-card {
  border-top: 3px solid color-mix(in srgb, var(--ch-accent, var(--accent)) 65%, transparent);
  background: color-mix(in srgb, var(--ch-accent, var(--accent)) 3%, var(--panel));
}

.section-card {

  h3 {
    font-size: 1.02rem;
    margin-bottom: 0.5rem;
  }
}

/* OnePager: festes 3×3-Raster über volle Breite und Höhe.
   Kein Lese-Zoom (bricht 100%-Höhen) — stattdessen sind die Schriften unten 1.2× skaliert. */
.guide-content.onepager {
  max-width: none;
  height: 100%;
  zoom: 1;
  padding: 0.9rem 1rem;
  display: flex;
  flex-direction: column;
}

.guide-content.onepager .guide-head,
.guide-content.onepager .chapter-title {
  display: none; /* Thema steht in der Info-Karte — Platz fürs Raster */
}

.guide-content.onepager .chapter {
  flex: 1;
  min-height: 0;
  margin-bottom: 0;
}

.guide-content.onepager .sections {
  height: 100%;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  grid-template-areas:
    "info beispiel voraussetzungen"
    "eigenschaften beispiel modern"
    "eigenschaften zusammenhaenge veraltet";
  gap: 0.6rem;
}

.guide-content.onepager .section-card {
  margin-bottom: 0;
  padding: 0.7rem 0.9rem;
  min-height: 0;
  overflow-y: auto;

  h3 {
    font-size: 1.06rem;
    margin-bottom: 0.3rem;
  }

  .section-body {
    font-size: 0.98rem;
  }
}

/* Farbkodiertes Cheat-Sheet: feste Akzentfarbe + Icon pro Karte */
.op-info { --op-accent: #3b82f6; }
.op-eigenschaften { --op-accent: #8b5cf6; --op-icon: "☰"; }
.op-beispiel { --op-accent: #64748b; --op-icon: "❯"; }
.op-zusammenhaenge { --op-accent: #14b8a6; --op-icon: "⇄"; }
.op-voraussetzungen { --op-accent: #f59e0b; --op-icon: "✓"; }
.op-modern { --op-accent: #22c55e; --op-icon: "✦"; }
.op-veraltet { --op-accent: #ef4444; --op-icon: "⚠"; }

.guide-content.onepager .section-card.op-card {
  border-top: 3px solid var(--op-accent);
  background: color-mix(in srgb, var(--op-accent) 5%, var(--panel));

  h3 {
    color: var(--op-accent);
    font-size: 0.95rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
  }

  h3::before {
    content: var(--op-icon, "");
    margin-right: 7px;
  }
}

/* Info-Karte: Thema als große Headline statt Uppercase-Label */
.guide-content.onepager .op-card.op-info h3 {
  font-size: 1.5rem;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text);
}

/* Mobil: eine Spalte in Quellreihenfolge (info → … → veraltet) */
@media (max-width: 900px) {
  .guide-content.onepager {
    height: auto;
  }

  .guide-content.onepager .sections {
    height: auto;
    display: flex;
    flex-direction: column;
  }

  .guide-content.onepager .section-card {
    overflow-y: visible;
  }
}

.ch-toggle {
  display: block;
  width: 100%;
  margin-top: 0.5rem;
  padding: 0.8rem 1rem;
  border: 1.5px dashed var(--border-strong);
  border-radius: 10px;
  background: var(--panel-soft);
  color: var(--text-muted);
  font: 600 0.9rem/1.2 inherit;
  font-family: inherit;
  text-align: center;
  cursor: pointer;
  transition: all 0.12s;

  &:hover {
    border-color: var(--accent);
    color: var(--accent);
    background: transparent;
  }

  &.is-done {
    border-style: solid;
    border-color: var(--success-border);
    background: var(--success-soft);
    color: var(--success);
  }
}

.empty-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--text-muted);
}

/* --- Markdown (Sections + Chat) --- */
.markdown :deep(p) {
  margin: 0 0 0.5em;
}

.markdown :deep(p:last-child) {
  margin-bottom: 0;
}

.markdown :deep(ul),
.markdown :deep(ol) {
  margin: 0.3em 0;
  padding-left: 1.2em;
}

.markdown :deep(li) {
  margin: 0.15em 0;
}

.markdown :deep(code) {
  background: var(--border);
  padding: 1px 4px;
  border-radius: 4px;
  font-family: "SF Mono", Consolas, monospace;
  font-size: 0.85em;
  /* Lange Bezeichner (Namespaces, Pfade) dürfen umbrechen statt zu überlaufen */
  overflow-wrap: anywhere;
}

.markdown :deep(pre) {
  background: var(--code-bg, #1e2330);
  color: var(--code-fg, #e6e8ee);
  padding: 10px 12px;
  border-radius: 8px;
  overflow-x: auto;
  margin: 0.5em 0;
}

.markdown :deep(pre code) {
  background: none;
  padding: 0;
  color: inherit;
  font-size: 0.85em;
}

.markdown :deep(h1),
.markdown :deep(h2),
.markdown :deep(h3) {
  font-size: 0.95em;
  margin: 0.6em 0 0.3em;
}

/* „Beispiel"-Überschriften in Karten als dezentes Uppercase-Label */
.section-card .markdown :deep(h3) {
  font-size: 0.74em;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-faint);
  margin: 0.9em 0 0.35em;
}

.markdown :deep(a) {
  color: var(--accent-hover);
}

.markdown :deep(table) {
  border-collapse: collapse;
  font-size: 0.95em;
}

.markdown :deep(th),
.markdown :deep(td) {
  border: 1px solid var(--border-strong);
  padding: 2px 6px;
}

/* Lesbarkeit: ~17px Fließtext, Zeilenhöhe 1.6, Textspalte max. ~70 Zeichen —
   Code-Blöcke dürfen die volle Kartenbreite nutzen */
.section-body {
  font-size: 1.0625rem;
  line-height: 1.6;
}

.section-card .markdown :deep(p),
.section-card .markdown :deep(ul),
.section-card .markdown :deep(ol) {
  max-width: 70ch;
}

.onepager .section-card .markdown :deep(p),
.onepager .section-card .markdown :deep(ul),
.onepager .section-card .markdown :deep(ol) {
  max-width: none; /* OnePager-Zellen sind selbst schmal genug */
}

/* --- Chat --- */
.chat-fab {
  position: fixed;
  right: 1.5rem;
  bottom: 1.5rem;
  width: 52px;
  height: 52px;
  border: none;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 1.4rem;
  cursor: pointer;
  box-shadow: 0 2px 12px var(--shadow);
  z-index: 20;
}

.chat-fab:hover {
  background: var(--accent-hover);
}

.elements-fab {
  right: 5.25rem;
}

/* Element-Sidebar (320px) offen → Chat links daneben anzeigen */
.chat-fab.shifted {
  right: calc(1.5rem + 320px);
}

.chat-panel.shifted {
  right: calc(1.5rem + 320px);
}

.chat-panel {
  position: fixed;
  right: 1.5rem;
  bottom: 1.5rem;
  width: 360px;
  height: 500px;
  max-height: calc(100vh - 3rem);
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 4px 24px var(--shadow);
  z-index: 20;
  overflow: hidden;
}

.chat-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.6rem 0.9rem;
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 600;
  font-size: 0.9rem;
}

.chat-close {
  border: none;
  background: none;
  color: var(--on-accent);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 0.9rem;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.chat-hint {
  color: var(--text-faint);
  font-size: 0.82rem;
  text-align: center;
  margin-top: 1rem;
}

.chat-msg {
  max-width: 85%;
  padding: 7px 11px;
  border-radius: 12px;
  font-size: 0.85rem;
  line-height: 1.4;
  white-space: pre-wrap;
  word-break: break-word;
}

.chat-msg.user {
  align-self: flex-end;
  background: var(--accent);
  color: var(--on-accent);
  border-bottom-right-radius: 3px;
}

.chat-msg.assistant {
  align-self: flex-start;
  background: var(--panel-soft);
  color: var(--text);
  border-bottom-left-radius: 3px;
}

.chat-msg.markdown {
  white-space: normal;
}

.chat-typing {
  color: var(--text-faint);
  font-style: italic;
}

.chat-input {
  display: flex;
  gap: 6px;
  padding: 0.6rem;
  border-top: 1px solid var(--border);
}

.chat-input textarea {
  flex: 1;
  resize: none;
  height: 38px;
  padding: 8px 10px;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  font-size: 0.85rem;
  font-family: inherit;
  outline: none;
}

.chat-input textarea:focus {
  border-color: var(--accent);
}

.chat-input button {
  width: 38px;
  border: none;
  border-radius: 8px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 1rem;
  cursor: pointer;
}

.chat-input button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
</style>
