<script setup>
import BlockPanel from './BlockPanel.vue'
import { renderMarkdown, renderBlocks } from '../markdown.js'
import { stufeFuer, SUB_RANK, VIEW_KURZ, VIEW_FARBE } from '../levels.js'
import { pruefeBlock, uebernehmeBlock, resetBlockProgress } from '../api.js'
import { clearPruef } from '../pruefungCache.js'
import { useConfirm } from '../composables/useConfirm.js'

const props = defineProps({
  block: { type: Object, required: true }, // { title, md, num }
  topic: { type: String, required: true },
  provider: { type: String, default: 'claude' },
  status: { type: Object, default: null },
  cap: { type: Number, default: 6 },
  guideId: { type: String, default: '' },
  tab: { type: String, default: 'exam' },
  ansicht: { type: String, default: 'compact' }, // compact | erklärend — left guide column
  hasPrev: { type: Boolean, default: false },
  hasNext: { type: Boolean, default: false },
  fortschritt: { type: Object, default: () => ({ total: 0, beginner: 0, advanced: 0, expert: 0, master: 0 }) },
})

import { computed, onMounted, onUnmounted, reactive, ref, watch } from 'vue'

const emit = defineEmits(['close', 'prev', 'next', 'statusChanged', 'setAnsicht', 'openSidebar', 'sectionUpdated'])

// --- Reset per block: questions session (slot) resp. progress (score) ---
const { isArmed, armOrRun } = useConfirm()
const resetN = ref(0)  // increment → panel remount (fresh slot, patterns reset)
const examKey = computed(() => `${props.topic}::${props.block.title}`)

// New question session: discard slot → remount loads patterns + pool fresh (fixes explain-only).
function resetQuestions() {
  clearPruef(examKey.value)
  resetN.value++
}

// Progress to 0: delete DB row, zero badge/learn state, fresh session.
async function resetProgress() {
  try {
    await resetBlockProgress(props.topic, props.block.title)
    emit('statusChanged', { block: props.block.title, good_answers: 0, streak: 0, cap: props.cap })
    clearPruef(examKey.value)
    resetN.value++
  } catch (e) { /* stay quiet — reset failed */ }
}

const guideEl = ref(null)  // left guide column (scroll target for ALT+↑/↓)
const rightEl = ref(null)  // right column (exam panel with input field)

// ALT is the modifier of the focus view. Plain arrows stay browser-default.
// ALT+←/→ pages blocks, ALT+↑/↓ scrolls the guide. A bare ALT tap
// (press+release without another key) toggles focus on the input field.
let altAlone = false
function onKeyDown(e) {
  if (e.key === 'Alt') { altAlone = true; e.preventDefault(); return }  // suppresses the Firefox menu bar
  if (e.ctrlKey || e.metaKey || !e.altKey) return  // plain/other → normal
  altAlone = false                                  // ALT+anything = no lone tap
  if (e.key === 'ArrowLeft') { e.preventDefault(); if (!e.repeat && props.hasPrev) emit('prev') }
  else if (e.key === 'ArrowRight') { e.preventDefault(); if (!e.repeat && props.hasNext) emit('next') }
  else if (e.key === 'ArrowUp') { e.preventDefault(); guideEl.value?.scrollBy(0, -120) }
  else if (e.key === 'ArrowDown') { e.preventDefault(); guideEl.value?.scrollBy(0, 120) }
}
function onKeyUp(e) {
  if (e.key === 'Alt') { e.preventDefault(); if (altAlone) { altAlone = false; toggleInput() } }
}
function resetAlt() { altAlone = false }  // window blur (ALT+Tab) → no false tap
function toggleInput() {
  // Answer field of the current form: explain = textarea, free gap-text = input.
  const el = rightEl.value?.querySelector('textarea, input')
  if (!el) return
  document.activeElement === el ? el.blur() : el.focus()
}
onMounted(() => {
  window.addEventListener('keydown', onKeyDown)
  window.addEventListener('keyup', onKeyUp)
  window.addEventListener('blur', resetAlt)
})
onUnmounted(() => {
  window.removeEventListener('keydown', onKeyDown)
  window.removeEventListener('keyup', onKeyUp)
  window.removeEventListener('blur', resetAlt)
})

const pct = (n) => (100 * n / (props.fortschritt.total || 1)) + '%'

// Accent color by the current block's level (green/blue/purple/gold) or neutral.
const levelColor = computed(() => {
  const s = props.status || {}
  return stufeFuer(s.good_answers || 0, s.cap || props.cap)?.farbe || 'var(--border)'
})
const level = computed(() => {
  const s = props.status || {}
  return stufeFuer(s.good_answers || 0, s.cap || props.cap)
})

// --- Check block (right-click on a section) ---
const displayedText = computed(() =>
  props.ansicht === 'compact' ? (props.block.compact || props.block.md) : props.block.md,
)
// Stufen-Segmente: mit subs wird je Sub separat gerendert (Rand+Badge in Stufen-Farbe),
// ohne subs (Legacy) bleibt der flache Pfad. Globaler Block-Index läuft über alle
// Segmente durch — Check/Vorschläge arbeiten unverändert über Index + raw.
const segments = computed(() => {
  const compact = props.ansicht === 'compact'
  const subs = props.block.subs
  let i = 0
  const seg = (level, text) => ({ level, blocks: renderBlocks(text).map((b) => ({ ...b, i: i++ })) })
  if (!subs || !subs.length) return [seg('', displayedText.value)]
  const out = []
  const anchor = compact ? (props.block.anker_compact || '') : (props.block.anchor || '')
  if (anchor.trim()) out.push(seg('', anchor))
  for (const sub of subs) {
    const body = compact ? (sub.compact || sub.md) : (sub.md || sub.compact)
    if (body && body.trim()) out.push(seg(sub.level, body))
  }
  return out
})
const blocks = computed(() => segments.value.flatMap((s) => s.blocks))
// Field that edits are applied to (must match the displayed text).
const spot = computed(() => (props.ansicht === 'compact' && props.block.compact) ? 'compact' : 'ausführlich')

const menu = reactive({ show: false, x: 0, y: 0, index: null })
function blockMenu(i, e) { menu.show = true; menu.x = e.clientX; menu.y = e.clientY; menu.index = i }
function closeMenu() { menu.show = false }

// Suggestion per block index: { new, running, error, editOpen, hint }
const suggestions = reactive({})

async function checkBlock(i, extra = '') {
  const raw = blocks.value[i]?.raw
  if (!raw || !props.guideId) return
  closeMenu()
  suggestions[i] = { revised: '', running: true, error: '', editOpen: false, hint: '' }
  try {
    const res = await pruefeBlock(props.guideId, { block: props.block.title, spot: spot.value, snippet: raw, hint: extra, provider: props.provider })
    suggestions[i] = { revised: res.revised, running: false, error: '', editOpen: false, hint: '' }
  } catch (e) {
    suggestions[i] = { revised: '', running: false, error: e.message || 'Exam failed', editOpen: false, hint: '' }
  }
}

async function applyBlock(i) {
  const v = suggestions[i]; const raw = blocks.value[i]?.raw
  if (!v || v.running || !raw) return
  v.running = true; v.error = ''
  try {
    const res = await uebernehmeBlock(props.guideId, { block: props.block.title, spot: spot.value, alt: raw, revised: v.revised, provider: props.provider })
    if (res.found) emit('sectionUpdated', { title: props.block.title, compact: res.compact, md: res.md })
    else { v.running = false; v.error = 'Spot not found — may have already changed.' }
  } catch (e) { v.running = false; v.error = e.message || 'Apply failed' }
}

function discardBlock(i) { delete suggestions[i] }
function editBlock(i) { const v = suggestions[i]; if (v) v.editOpen = !v.editOpen }
function sendBlockEdit(i) {
  const z = (suggestions[i]?.hint || '').trim()
  if (z) checkBlock(i, z)
}

// Block/content switch → reset suggestions + menu (block indices change).
watch(() => `${props.block.title}|${props.block.md}|${props.block.compact || ''}`, () => {
  for (const k of Object.keys(suggestions)) delete suggestions[k]
  closeMenu()
})
</script>

<template>
  <div class="fokus-overlay" :style="{ '--stand': levelColor }">
    <div class="fokus-bar">
      <div class="fokus-bar-inner">
        <button class="fokus-btn" title="Open navigation" @click="$emit('openSidebar')">☰</button>
        <button class="fokus-btn" :disabled="!hasPrev" title="Previous block" @click="$emit('prev')">←</button>
        <button class="fokus-btn" :disabled="!hasNext" title="Next block" @click="$emit('next')">→</button>
        <span class="fokus-title">{{ block.title }}</span>
        <span v-if="level" class="stand-badge" :style="{ color: level.farbe, borderColor: level.farbe }">{{ level.kurz }} {{ level.label }}</span>
        <span class="fokus-spacer"></span>
        <button class="fokus-btn" title="Reset questions (new question session)" @click="resetQuestions">↻</button>
        <button
          class="fokus-btn"
          :class="{ armed: isArmed('reset-fortschritt') }"
          :title="isArmed('reset-fortschritt') ? 'Click again: set progress to 0' : 'Reset progress (score to 0)'"
          @click="armOrRun('reset-fortschritt', resetProgress)"
        >⟲</button>
        <button class="fokus-btn" title="Exit full view" @click="$emit('close')">✕</button>
      </div>
    </div>
    <div class="fokus-xp" :title="`${fortschritt.beginner}/${fortschritt.total} from Beginner · ${fortschritt.advanced} Advanced · ${fortschritt.expert} Expert · ${fortschritt.master} Master`">
      <div class="xp-seg" :style="{ width: pct(fortschritt.master), background: 'var(--level-master)' }"></div>
      <div class="xp-seg" :style="{ width: pct(fortschritt.expert - fortschritt.master), background: 'var(--level-expert)' }"></div>
      <div class="xp-seg" :style="{ width: pct(fortschritt.advanced - fortschritt.expert), background: 'var(--level-advanced)' }"></div>
      <div class="xp-seg" :style="{ width: pct(fortschritt.beginner - fortschritt.advanced), background: 'var(--level-beginner)' }"></div>
    </div>
    <div class="fokus-body">
      <div ref="guideEl" class="fokus-col left">
        <div class="markdown">
          <template v-for="(seg, si) in segments" :key="si">
            <div :class="{ 'sub-stufe': !!seg.level }"
                 :style="seg.level ? { '--stufe-farbe': VIEW_FARBE[SUB_RANK[seg.level] || 1] } : null">
              <span v-if="seg.level" class="sub-stufe-badge"
                    :title="`Stufe ${VIEW_KURZ[SUB_RANK[seg.level] || 1]}`">{{ VIEW_KURZ[SUB_RANK[seg.level] || 1] }}</span>
              <template v-for="b in seg.blocks" :key="b.i">
                <div class="md-block" v-html="b.html" @contextmenu.prevent="blockMenu(b.i, $event)"></div>
                <div v-if="suggestions[b.i]" class="block-vorschlag">
                  <div v-if="suggestions[b.i].running" class="bv-status">Check Section…</div>
                  <template v-else>
                    <p v-if="suggestions[b.i].error" class="bv-fehler">{{ suggestions[b.i].error }}</p>
                    <div class="markdown bv-new" v-html="renderMarkdown(suggestions[b.i].revised)"></div>
                    <div class="bv-aktionen">
                      <button class="bv-btn ja" title="Apply" @click="applyBlock(b.i)">✓</button>
                      <button class="bv-btn" title="Discard" @click="discardBlock(b.i)">✗</button>
                      <button class="bv-btn" :class="{ aktiv: suggestions[b.i].editOpen }" title="Add hint" @click="editBlock(b.i)">✏️</button>
                    </div>
                    <div v-if="suggestions[b.i].editOpen" class="bv-edit">
                      <input v-model="suggestions[b.i].hint" class="bv-input" placeholder="Extra info → check again" @keyup.enter="sendBlockEdit(b.i)" />
                      <button class="bv-btn ja" title="Check again" @click="sendBlockEdit(b.i)">↻</button>
                    </div>
                  </template>
                </div>
              </template>
            </div>
          </template>
        </div>
      </div>
      <div v-if="menu.show" class="menu-overlay" @click="closeMenu" @contextmenu.prevent="closeMenu">
        <div class="block-menu" :style="{ top: menu.y + 'px', left: menu.x + 'px' }" @click.stop>
          <button class="bm-item" @click="checkBlock(menu.index)">Check</button>
        </div>
      </div>
      <div ref="rightEl" class="fokus-col right">
        <BlockPanel
          mode="full"
          :key="block.title + '|' + tab + '|' + resetN"
          :initial-tab="tab"
          :topic="topic"
          :block="block.title"
          :section="block.md"
          :section-compact="block.compact || ''"
          :provider="provider"
          :status="status"
          :cap="cap"
          :ansicht="ansicht"
          @set-ansicht="$emit('setAnsicht', $event)"
          @status-changed="$emit('statusChanged', $event)"
        />
      </div>
    </div>
  </div>
</template>

<style scoped>
.fokus-overlay {
  position: fixed;
  inset: 0;
  z-index: 40;
  /* Semi-transparent + blur: the guide list behind shows blurred through the gray surfaces. */
  background: color-mix(in srgb, var(--bg-preview) 60%, transparent);
  backdrop-filter: blur(10px);
  display: grid;
  grid-template-rows: auto auto 1fr; /* header / XP bar / body */
}
.fokus-bar {
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--border);
  background: var(--panel);
}
/* Header content aligns with the body (same max-width + inner padding). */
.fokus-bar-inner {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  max-width: 1600px;
  width: 100%;
  margin-inline: auto;
  padding-inline: 1.25rem;
}
.fokus-spacer { flex: 1; }

.stand-badge {
  margin-left: 0.5rem;
  padding: 0.12rem 0.6rem;
  font-size: 0.72rem; font-weight: 600;
  border-radius: 999px; border: 1px solid; white-space: nowrap;
}
.stand-badge.gruen { background: var(--success-soft); border-color: var(--success-border); color: var(--success); }
.stand-badge.lila  { background: color-mix(in srgb, #8b5cf6 16%, var(--panel)); border-color: #8b5cf6; color: #6d28d9; }
.stand-badge.gold  { background: color-mix(in srgb, #d4af37 20%, var(--panel)); border-color: #d4af37; color: #8a6d12; }

/* Experience bar on top: fills from the left — gold (mastered) → purple (understood) → green (completed). */
.fokus-xp { position: relative; display: flex; height: 8px; background: var(--panel-soft); }
/* 9 divider lines every 10% → 10 visible segments (fill stays continuous). */
.fokus-xp::after {
  content: '';
  position: absolute; inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(
    to right,
    transparent 0,
    transparent calc(10% - 2px),
    var(--panel) calc(10% - 2px),
    var(--panel) 10%
  );
}
.xp-seg { height: 100%; transition: width 0.3s ease; }
.xp-seg.gold { background: #d4af37; }
.xp-seg.lila { background: #8b5cf6; }
.xp-seg.gruen { background: var(--success-border); }
.fokus-title { font-weight: 600; font-size: 0.95rem; margin-left: 0.5rem; }
.fokus-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 2rem; height: 2rem; padding: 0 0.5rem;
  font-size: 1rem;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: var(--panel);
  color: var(--text);
  cursor: pointer;
}
.fokus-btn:hover { border-color: var(--accent); }
.fokus-btn:disabled { opacity: 0.4; cursor: default; }
.fokus-btn.armed { border-color: var(--danger, #dc2626); color: var(--danger, #dc2626); background: color-mix(in srgb, var(--danger, #dc2626) 12%, var(--panel)); }

/* Two raised cards on a gray "desk" (--bg-preview from the overlay). */
.fokus-body {
  min-height: 0;
  display: flex;
  gap: 1.25rem;
  padding: 1.25rem;
  max-width: 1600px;
  width: 100%;
  margin-inline: auto;
}
.fokus-col {
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  /* Card tilts by block level: colored border + tinted background (green/purple/gold). */
  background: color-mix(in srgb, var(--stand) 7%, var(--panel));
  border: 1px solid var(--stand);
  border-top: 3px solid var(--stand);
  border-radius: 12px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
}
/* Left: wide reading card, text centered at reading width. */
.fokus-col.left { flex: 1; padding: 2rem 2.5rem; }
.fokus-col.left > * { max-width: 74ch; margin-inline: auto; }
/* Right: work card; the panel inside is borderless (the card is the frame). */
.fokus-col.right { flex: none; width: clamp(440px, 34%, 600px); padding: 1.5rem; }
.fokus-col.right :deep(.bp) { margin-top: 0; }
.fokus-col.right :deep(.bp-panel) { border: none; background: transparent; padding: 0; }
.fokus-h2 { font-size: 1.1rem; margin: 0 0 0.75rem; }

/* Desktop: the right card as a flex column — exam/chat history fills the
   full height and scrolls internally, input + buttons stay at the bottom. */
@media (min-width: 901px) {
  .fokus-col.right { display: flex; flex-direction: column; overflow: hidden; }
  .fokus-col.right :deep(.bp) { flex: 1; display: flex; flex-direction: column; min-height: 0; }
  .fokus-col.right :deep(.bp-panel) { flex: 1; display: flex; flex-direction: column; min-height: 0; overflow-y: auto; }
  .fokus-col.right :deep(.bp-panel > div) { flex: 1; display: flex; flex-direction: column; min-height: 0; }
  .fokus-col.right :deep(.bp-messages) { flex: 1; min-height: 0; max-height: none; }
}

@media (max-width: 900px) {
  .fokus-body { flex-direction: column; overflow-y: auto; }
  .fokus-col { overflow-y: visible; }
  .fokus-col.right { width: auto; }
}

/* Check block: right-click menu + suggestion below the section */
/* Keep the spacing on the wrapper — the inner p is now :last-child (margin 0). */
.md-block { border-radius: 6px; transition: background 0.15s; margin-bottom: 0.8em; }
.md-block:last-child { margin-bottom: 0; }
.md-block > :first-child { margin-top: 0; }
.md-block > :last-child { margin-bottom: 0; }
.md-block:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); }

.menu-overlay { position: fixed; inset: 0; z-index: 60; }
.block-menu {
  position: fixed;
  min-width: 8rem;
  padding: 0.25rem;
  background: var(--panel);
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
}
.bm-item {
  display: block;
  width: 100%;
  padding: 0.4rem 0.7rem;
  text-align: left;
  font-size: 0.9rem;
  border: none;
  border-radius: 5px;
  background: transparent;
  color: var(--text);
  cursor: pointer;
}
.bm-item:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }

.block-vorschlag {
  margin: 0.5rem 0 1rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--accent);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 6%, var(--panel));
}
.bv-status { font-size: 0.9rem; color: var(--text-soft, #888); }
.bv-fehler { color: var(--danger, #dc2626); font-size: 0.88rem; margin: 0 0 0.5rem; }
.bv-new > :first-child { margin-top: 0; }
.bv-new > :last-child { margin-bottom: 0; }
.bv-aktionen { display: flex; gap: 0.4rem; margin-top: 0.6rem; }
.bv-btn {
  min-width: 2rem; height: 2rem; padding: 0 0.5rem;
  font-size: 0.95rem;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: var(--panel);
  color: var(--text);
  cursor: pointer;
}
.bv-btn:hover { border-color: var(--accent); }
.bv-btn.aktiv { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, var(--panel)); }
.bv-btn.ja { border-color: var(--success-border); color: var(--success); }
.bv-edit { display: flex; gap: 0.4rem; margin-top: 0.5rem; }
.bv-input {
  flex: 1;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--panel);
  color: var(--text);
  font-size: 0.9rem;
}
</style>
