<script setup>
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
import { api } from '../api.js'
import { render, lesestat } from '../markdown.js'

const props = defineProps({ daten: Object, topic: String })
const emit = defineEmits(['schliessen'])

const SCHWELLE = 10  // Anzeige; die Wahrheit entscheidet der Server (PRUEFUNG_SCHWELLE)

const wurzel = ref(null)
const pos = ref(0)
const fertig = ref(new Set())      // baustein-ids mit bestandener Prüfung
const xpMap = ref({})              // baustein-id → Saldo

// Screen-Liste: je Kapitel ein Intro, je Baustein Fundament → Abruf → Prüfung.
const screens = computed(() => {
  const out = []
  const kaps = props.daten?.kapitel || []
  kaps.forEach((kap, ki) => {
    out.push({ typ: 'intro', kap, nr: ki + 1, von: kaps.length })
    for (const s of kap.sections) {
      out.push({ typ: 'fundament', baustein: s.baustein, titel: s.titel, lang: s.lang })
      out.push({ typ: 'abruf', baustein: s.baustein, titel: s.titel })
      out.push({ typ: 'pruefung', baustein: s.baustein, titel: s.titel })
    }
  })
  out.push({ typ: 'ende' })
  return out
})
const screen = computed(() => screens.value[pos.value] || { typ: 'ende' })

const bausteinAnzahl = computed(() =>
  (props.daten?.kapitel || []).reduce((a, k) => a + k.sections.length, 0))
const fortschrittText = computed(() => `${fertig.value.size} / ${bausteinAnzahl.value} Bausteine`)

// ── Stats (wie Guide.vue: 100 Wörter/min + 5 s je Display-Formel) ──────────────
function zeit(min) { return !min ? '~0 min' : min < 1 ? '<1 min' : `~${Math.round(min)} min` }
function kapStat(kap) {
  let w = 0, f = 0
  for (const s of kap.sections) { const t = lesestat(s.lang || ''); w += t.woerter; f += t.displayFormeln }
  return { woerter: w, minuten: w / 100 + f * 5 / 60 }
}

const htmlCache = new Map()
function fundamentHtml(s) {
  if (!htmlCache.has(s.baustein)) htmlCache.set(s.baustein, render(s.lang))
  return htmlCache.get(s.baustein)
}

// ── Navigation + Prüfungs-Gate ─────────────────────────────────────────────────
// Lesen + Abruf sind frei. Nur die Prüfung sperrt: weiter erst ab Saldo ≥ Schwelle.
// 0 Panels sperren NICHT (leerer Baustein darf den Guide nie blockieren).
const gesperrt = computed(() =>
  screen.value.typ === 'pruefung' && panels.value.length > 0
  && !fertig.value.has(screen.value.baustein))
function vor() { if (!gesperrt.value && pos.value < screens.value.length - 1) pos.value++ }
function zurueck() { if (pos.value > 0) pos.value-- }
const buehne = ref(null)
function taste(e) {
  if (e.key === 'ArrowRight') vor()
  else if (e.key === 'ArrowLeft') zurueck()
  // Pfeil hoch/runter scrollen die Bühne — der innere Scroller hat nie Fokus,
  // ohne das hier bewegen die Tasten also gar nichts
  else if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
    e.preventDefault()
    buehne.value?.scrollBy({ top: e.key === 'ArrowDown' ? 140 : -140, behavior: 'smooth' })
  }
  // Abruf: Leertaste deckt auf, 1 = falsch, 2 = richtig
  else if (screen.value.typ === 'abruf' && stapel.value.length) {
    if (e.key === ' ') { e.preventDefault(); zeigeAntwort.value = true }
    else if (zeigeAntwort.value && e.key === '1') antworten(false)
    else if (zeigeAntwort.value && e.key === '2') antworten(true)
  }
  // Prüfung: 1–4 toggeln die Aussagen, Leertaste prüft / blättert zum nächsten Panel
  else if (screen.value.typ === 'pruefung' && panel.value.length) {
    if (e.key === ' ') {
      e.preventDefault()
      aufloesung.value ? naechstesPanel() : pruefen()
    } else if (['1', '2', '3', '4'].includes(e.key)) {
      const x = panel.value[Number(e.key) - 1]
      if (x) toggle(x.id)
    }
  }
}

// Wisch-Navigation (mobil): klar horizontal + kurz genug = blättern.
// Vertikales Scrollen und Text-Markieren bleiben unberührt (dy-Vergleich).
let wisch = null
function wischStart(e) {
  // Start auf horizontal scrollbarem Element (breite Formel/Tabelle):
  // der Wisch gehört dem Element, nicht der Seiten-Navigation
  for (let el = e.target; el && el !== e.currentTarget; el = el.parentElement) {
    if (el.scrollWidth > el.clientWidth + 1) { wisch = null; return }
  }
  const t = e.touches[0]
  wisch = { x: t.clientX, y: t.clientY }
}
function wischEnde(e) {
  if (!wisch) return
  const t = e.changedTouches[0]
  const dx = t.clientX - wisch.x
  const dy = t.clientY - wisch.y
  wisch = null
  if (Math.abs(dx) < 60 || Math.abs(dx) < 2 * Math.abs(dy)) return
  if (dx < 0) vor()
  else zurueck()
}

// ── Abrufprüfung (Karteikarten) ────────────────────────────────────────────────
// Persistenz über Leitner (DB): richtig beantwortete Karten sind bis zur
// Wiedervorlage nicht fällig und erscheinen beim nächsten Besuch nicht mehr.
const stapel = ref([])
const alleKarten = ref([])   // gefüllt, wenn alles absolviert → „Alle erneut üben"
const zeigeAntwort = ref(false)
const sende = ref(false)

async function abrufLaden(bausteinId) {
  zeigeAntwort.value = false
  alleKarten.value = []
  stapel.value = await api.bausteinKarten(props.topic, bausteinId)
  if (!stapel.value.length)
    alleKarten.value = await api.bausteinKarten(props.topic, bausteinId, true)
}
function nochmalAlle() {
  stapel.value = alleKarten.value
  alleKarten.value = []
  zeigeAntwort.value = false
}
async function antworten(richtig) {
  if (sende.value || !stapel.value.length) return
  sende.value = true
  try {
    const karte = stapel.value[0]
    await api.antwort(karte.id, richtig)
    stapel.value = richtig ? stapel.value.slice(1) : [...stapel.value.slice(1), karte]
    zeigeAntwort.value = false
    if (!stapel.value.length) await abrufLaden(screen.value.baustein)
  } finally { sende.value = false }
}

// ── Prüfung (4er-Panels, exakte Teilmenge ankreuzen) ───────────────────────────
const panels = ref([])
const panelIdx = ref(0)
const auswahl = ref(new Set())
const aufloesung = ref(null)       // nach dem Prüfen: [{id, wahr, erklaerung}]
const warRichtig = ref(false)
const saldo = ref(0)
const panel = computed(() => panels.value[panelIdx.value]?.panel || [])

async function pruefungLaden(bausteinId) {
  panels.value = await api.pruefung(props.topic, bausteinId)
  panelIdx.value = 0; auswahl.value = new Set(); aufloesung.value = null
  saldo.value = xpMap.value[bausteinId] || 0
  if (!panels.value.length && !fertig.value.has(bausteinId)) {
    // keine Aussagen generiert → Baustein nicht blockieren, als erledigt werten
    fertig.value = new Set([...fertig.value, bausteinId])
    await api.bausteinFertig(props.topic, bausteinId).catch(() => {})
  }
}
function toggle(id) {
  if (aufloesung.value) return
  const s = new Set(auswahl.value)
  s.has(id) ? s.delete(id) : s.add(id)
  auswahl.value = s
}
async function pruefen() {
  if (aufloesung.value || sende.value) return
  sende.value = true
  try {
    const ids = panel.value.map(x => x.id)
    const r = await api.pruefungAntwort(props.topic, ids, [...auswahl.value])
    aufloesung.value = r.aufloesung
    warRichtig.value = r.richtig
    saldo.value = r.xp
    xpMap.value = { ...xpMap.value, [screen.value.baustein]: r.xp }
    if (r.fertig) fertig.value = new Set([...fertig.value, screen.value.baustein])
  } finally { sende.value = false }
}
async function naechstesPanel() {
  aufloesung.value = null; auswahl.value = new Set()
  if (panelIdx.value < panels.value.length - 1) panelIdx.value++
  else await pruefungLaden(screen.value.baustein)  // neu mischen, Nachschub
}
function urteil(id) {
  const a = (aufloesung.value || []).find(x => x.id === id)
  return a ? a.wahr : null
}

watch(screen, (s) => {
  if (s.typ === 'abruf') abrufLaden(s.baustein)
  else if (s.typ === 'pruefung') pruefungLaden(s.baustein)
})

// ── Fullscreen + Resume ────────────────────────────────────────────────────────
function schliessen() {
  if (document.fullscreenElement) document.exitFullscreen().catch(() => {})
  emit('schliessen')
}
onMounted(async () => {
  window.addEventListener('keydown', taste)
  try { await wurzel.value?.requestFullscreen() } catch { /* CSS-Overlay reicht */ }
  const stand = await api.lernstand(props.topic).catch(() => [])
  fertig.value = new Set(stand.filter(s => s.status === 'fertig').map(s => s.baustein_id))
  xpMap.value = Object.fromEntries(stand.map(s => [s.baustein_id, s.xp]))
  const idx = screens.value.findIndex(s => s.typ === 'fundament' && !fertig.value.has(s.baustein))
  pos.value = idx >= 0 ? idx : screens.value.length - 1
})
onUnmounted(() => {
  window.removeEventListener('keydown', taste)
  if (document.fullscreenElement) document.exitFullscreen().catch(() => {})
})
</script>

<template>
  <div ref="wurzel" class="lesemodus"
       @touchstart.passive="wischStart" @touchend.passive="wischEnde">
    <header class="lm-kopf">
      <span class="lm-fort">{{ fortschrittText }}</span>
      <button class="lm-x" title="Schließen" @click="schliessen">✕</button>
    </header>

    <main ref="buehne" class="lm-buehne">
      <section v-if="screen.typ === 'intro'" class="lm-screen lm-intro">
        <div class="lm-kapnr">Kapitel {{ screen.nr }} / {{ screen.von }}</div>
        <h1>{{ screen.kap.titel }}</h1>
        <p v-if="screen.kap.intro" class="lm-introtext">{{ screen.kap.intro }}</p>
        <div class="lm-stats">
          {{ kapStat(screen.kap).woerter.toLocaleString('de-DE') }} Wörter ·
          {{ zeit(kapStat(screen.kap).minuten) }} · {{ screen.kap.sections.length }} Bausteine
        </div>
      </section>

      <section v-else-if="screen.typ === 'fundament'" class="lm-screen">
        <div class="lm-label">Fundament</div>
        <h2 class="lm-titel">{{ screen.titel }}</h2>
        <div class="markdown" v-html="fundamentHtml(screen)"></div>
      </section>

      <section v-else-if="screen.typ === 'abruf'" class="lm-screen lm-abruf">
        <div class="lm-label">Abrufprüfung · {{ screen.titel }}</div>
        <div v-if="stapel.length" class="lm-karte">
          <div class="lm-frage markdown" v-html="render(stapel[0].inhalt.frage)"></div>
          <div v-if="zeigeAntwort" class="lm-antwort markdown" v-html="render(stapel[0].inhalt.antwort)"></div>
          <div class="lm-karte-akt">
            <button v-if="!zeigeAntwort" @click="zeigeAntwort = true">
              Antwort zeigen <kbd class="kurz">_</kbd></button>
            <template v-else>
              <button class="lm-falsch" @click="antworten(false)">
                Falsch <kbd class="kurz">1</kbd></button>
              <button class="lm-richtig" @click="antworten(true)">
                Richtig <kbd class="kurz">2</kbd></button>
            </template>
          </div>
          <div class="lm-rest">noch {{ stapel.length }} · Box {{ stapel[0].box }}</div>
        </div>
        <div v-else-if="alleKarten.length" class="lm-bestanden">
          ✓ Alle Karten absolviert — Wiedervorlage folgt automatisch.<br />
          <button style="margin-top: 12px" @click="nochmalAlle">Alle erneut üben</button>
        </div>
        <div v-else class="lm-bestanden">✓ Abruf durch — weiter mit →</div>
      </section>

      <section v-else-if="screen.typ === 'pruefung'" class="lm-screen lm-pruefung">
        <div class="lm-label">Prüfung · {{ screen.titel }} · Saldo {{ saldo }} / {{ SCHWELLE }}</div>
        <template v-if="panel.length">
          <h3 class="pf-frage">Was gilt? <span class="pf-hinweis">(0–{{ panel.length }} Aussagen können wahr sein)</span></h3>
          <div class="pf-panel">
            <label v-for="(x, i) in panel" :key="x.id" class="pf-aussage"
                   :class="{ gewaehlt: auswahl.has(x.id),
                             'pf-wahr': urteil(x.id) === true,
                             'pf-falsch2': urteil(x.id) === false }"
                   @click.prevent="toggle(x.id)">
              <kbd class="kurz">{{ i + 1 }}</kbd>
              <span class="markdown" v-html="render(x.text)"></span>
            </label>
          </div>
          <div v-if="aufloesung" class="pf-feedback" :class="warRichtig ? 'pf-fb-ok' : 'pf-fb-bad'">
            {{ warRichtig ? '✓ Panel korrekt (+1)' : '✗ Nicht exakt (−1)' }}
          </div>
          <div class="pf-akt">
            <button v-if="!aufloesung" @click="pruefen">Prüfen <kbd class="kurz">_</kbd></button>
            <button v-else @click="naechstesPanel">Nächstes Panel → <kbd class="kurz">_</kbd></button>
            <span v-if="fertig.has(screen.baustein)" class="lm-bestanden" style="margin: 0">✓ bestanden</span>
          </div>
        </template>
        <div v-else class="lm-bestanden">Keine Prüfungs-Aussagen für diesen Baustein — weiter mit →</div>
      </section>

      <section v-else class="lm-screen lm-ende">
        <h1>Fundament abgeschlossen 🎉</h1>
        <p class="lm-introtext">Schritt 2 (Anwendung) und Schritt 3 (eigene Aufgaben) folgen.</p>
      </section>
    </main>

    <footer class="lm-fuss">
      <button :disabled="pos === 0" @click="zurueck">← Zurück</button>
      <button :disabled="gesperrt || pos >= screens.length - 1" @click="vor">
        {{ gesperrt ? `Saldo ${saldo} / ${SCHWELLE} — weiter prüfen` : 'Weiter →' }}
      </button>
    </footer>
  </div>
</template>
