<script setup>
import { ref, computed, watch, onUnmounted } from 'vue'
import { fetchBlocksBoard, runQa, runRepair } from '../api.js'
import KanbanBoard from './KanbanBoard.vue'
import GuideBoardSection from './GuideBoardSection.vue'

const props = defineProps({
  topic: { type: String, required: true },
  generating: { type: Boolean, default: false },
  progress: { type: String, default: null },
  ready: { type: Boolean, default: false },
  partial: { type: Boolean, default: false },
  guideFormat: { type: String, default: 'Guide' },
})
const emit = defineEmits(['close', 'resetStage', 'restartAll', 'continueAll', 'addResearch',
  'requeueDead', 'removeAll', 'cancel', 'cancelGuide', 'startGuide', 'resetGuideStage', 'preview', 'removeFormat', 'restartCard', 'resetGuideCard'])

// ── Blocks-Pipeline (Poll 1.2s solange generiert) ──────────────────────────────
const board = ref(null)
let timer = null

async function pollBoard() {
  try {
    board.value = await fetchBlocksBoard(props.topic)
  } catch { /* Board noch leer */ }
}
function startPoll() { stopPoll(); timer = setInterval(pollBoard, 1200) }
function stopPoll() { if (timer) { clearInterval(timer); timer = null } }

watch(() => props.topic, () => { board.value = null; pollBoard() }, { immediate: true })
watch(() => props.generating, (g) => {
  if (g) startPoll()
  else { stopPoll(); pollBoard() }  // Endstand nachladen
}, { immediate: true })
onUnmounted(stopPoll)

const inventoryCols = computed(() => (board.value?.columns || []).filter((c) => c.board === 'inventory'))
const artefactCols = computed(() => (board.value?.columns || []).filter((c) => c.board === 'artefacts'))
const dead = computed(() => board.value?.dead || [])
const qa = computed(() => board.value?.qa || null)

// Spalten, auf die zurückgesetzt werden kann (Terminal-Spalten sind kein Reset-Ziel).
const RESETTABLE = new Set(['ingest', 'cluster', 'pair_check', 'consensus_gate', 'clarify', 'naming',
  'naming_check', 'fragment_filter', 'grouping', 'gap_check', 'done',
  'subblocks', 'facts', 'konsolidierung', 'levels', 'relevance', 'question_pattern', 'artefacts', 'finalize', 'outline'])
const sel = ref(null)          // gewählte Spalte {board, key, label}
const selCard = ref(null)      // gewählte Karte (Einzel-Restart, nur artefacts)
const confirm = ref(null)      // 2-Klick-Bestätigung für destruktive Aktionen

function stageClick(c) {
  if (props.generating || !RESETTABLE.has(c.key)) return
  confirm.value = null
  selCard.value = null
  sel.value = sel.value?.key === c.key ? null : { board: c.board, key: c.key, label: c.label }
}

function cardClick(k) {
  if (props.generating || k.kind !== 'ablock') return  // Einzel-Restart nur für Artefakt-Karten
  confirm.value = null
  sel.value = null
  selCard.value = selCard.value?.card_id === k.card_id ? null : k
}

function restartCard() {
  const k = selCard.value
  selCard.value = null
  confirm.value = null
  later(() => emit('restartCard', k.card_id))
}
function arm(action, fn) {
  if (confirm.value === action) { confirm.value = null; fn() }
  else confirm.value = action
}
function later(fn) {  // Aktion emitten, Board kurz danach neu laden (kein generating-Poll aktiv)
  fn()
  setTimeout(pollBoard, 600)
}

function resetHere(restart) {
  const s = sel.value
  sel.value = null
  confirm.value = null
  later(() => emit('resetStage', { board: s.board, stage: s.key, restart }))
}

const qaBusy = ref(false)
const guideRefresh = ref(0)  // QA/Repair schreiben auch den Guide-Report → Badge neu laden
async function runQaClick() {
  if (qaBusy.value) return
  qaBusy.value = true
  try {
    await runQa(props.topic)
  } finally {
    qaBusy.value = false
    pollBoard()
    guideRefresh.value++
  }
}

const repairBusy = ref(false)
const repairInfo = ref('')
async function repairClick() {
  if (repairBusy.value) return
  repairBusy.value = true
  repairInfo.value = ''
  try {
    const r = await runRepair(props.topic)
    const n = (r.hygiene || []).length + (r.merges || []).length + (r.sub_merges || []).length
      + (r.entfernt || []).length + (r.aufgeraeumt || 0) + (r.freigesprochen || []).length
    repairInfo.value = n === 0
      ? 'keine behebbaren Befunde'
      : `${(r.hygiene || []).length} Titel · ${(r.merges || []).length} Merges · ${(r.sub_merges || []).length} Sub-Merges · ${(r.entfernt || []).length} entfernt · ${r.aufgeraeumt || 0} aufgeräumt · ${(r.freigesprochen || []).length} freigesprochen`
  } catch (e) {
    repairInfo.value = String(e.message || e)
  } finally {
    repairBusy.value = false
    pollBoard()
  }
}
</script>

<template>
  <div class="gen-view">
    <header class="gen-head">
      <h1>{{ topic }}</h1>
      <span class="gen-sub">Generierung</span>
      <span class="gen-spacer"></span>
      <button class="gen-close" title="Close" @click="emit('close')">✕</button>
    </header>

    <div v-if="qa && qa.pausiert" class="qa-pause">
      <strong>QA-Gate: Note {{ qa.note.toFixed(1) }} unter Schwelle {{ qa.schwelle }} — pausiert.</strong>
      <span v-if="qa.befunde.length"> Befunde: {{ qa.befunde.join(' · ') }}</span>
      <button class="gen-act" @click="emit('continueAll', { qaForce: true })">Trotzdem fortsetzen</button>
    </div>
    <section class="gen-section">
      <div class="gen-steps-top">
        <span class="gen-title">Bausteine</span>
        <div v-if="progress" class="gen-progress"><span class="gen-progress-dot"></span>{{ progress }}</div>
        <div v-if="!generating" class="gen-actions">
          <button class="gen-act" :disabled="qaBusy" title="QA-Lauf wie am Gate (inkl. LLM-Stichprobe)"
                  @click="runQaClick">{{ qaBusy ? 'QA läuft…' : 'QA' }}</button>
          <button v-if="qa" class="gen-act" :disabled="repairBusy"
                  title="QA-Befunde gezielt beheben: Hygiene, bestätigte Dubletten mergen, Fremd/Unecht nach Gegen-Judge entfernen"
                  @click="repairClick">{{ repairBusy ? 'Repariert…' : 'Befunde beheben' }}</button>
          <span v-if="repairInfo" class="repair-info">{{ repairInfo }}</span>
          <button class="gen-act play" @click="emit('restartAll')">{{ ready || partial ? '+ Research' : 'Generate' }}</button>
          <button v-if="partial" class="gen-act" @click="emit('continueAll')">Continue</button>
          <button
            v-if="ready || partial"
            class="gen-act danger"
            :class="{ armed: confirm === 'remove' }"
            @click="arm('remove', () => later(() => emit('removeAll')))"
          >{{ confirm === 'remove' ? 'Sure?' : 'Remove' }}</button>
        </div>
        <div v-else class="gen-actions">
          <button class="gen-act" @click="emit('addResearch')">+ Research</button>
          <button class="gen-act danger" @click="emit('cancel')">Cancel</button>
        </div>
        <button
          v-if="dead.length"
          class="gen-act"
          :title="dead.map((d) => d.title + ': ' + d.error).join('\n')"
          @click="later(() => emit('requeueDead'))"
        >⟳ {{ dead.length }} dead</button>
      </div>

      <div class="gen-board-label">
        Inventar
        <span v-if="qa" class="qa-note" :class="qa.note >= qa.schwelle ? 'ok' : 'bad'"
              :title="'QA-Schwelle ' + qa.schwelle">QA {{ qa.note.toFixed(1) }}/10</span>
      </div>
      <KanbanBoard
        :columns="inventoryCols"
        :agents="board?.agents || []"
        :generating="generating"
        :selectable="!generating"
        :selectedKey="sel?.board === 'inventory' ? sel.key : null"
        @stageClick="stageClick"
      />
      <div class="gen-board-label">
        Artefakte
        <span v-if="qa && qa.note_artefakte != null" class="qa-note"
              :class="qa.note_artefakte >= qa.schwelle ? 'ok' : 'bad'"
              title="Beleg-Quote + verwaiste Artefakte">QA {{ qa.note_artefakte.toFixed(1) }}/10</span>
      </div>
      <KanbanBoard
        :columns="artefactCols"
        :generating="generating"
        :selectable="!generating"
        :cardSelectable="!generating"
        :selectedKey="sel?.board === 'artefacts' ? sel.key : null"
        @stageClick="stageClick"
        @cardClick="cardClick"
      />

      <div v-if="selCard && !generating" class="gen-step-actions">
        <span class="gen-step-actions-label">Karte «{{ selCard.title }}»:</span>
        <button class="gen-act play" :class="{ armed: confirm === 'card' }" @click="confirm === 'card' ? restartCard() : confirm = 'card'">{{ confirm === 'card' ? 'Sure?' : '↻ Karte neu generieren' }}</button>
        <button class="gen-act ghost" @click="selCard = null; confirm = null">Abbrechen</button>
      </div>
      <div v-if="sel && !generating" class="gen-step-actions">
        <span class="gen-step-actions-label">Ab «{{ sel.label }}»:</span>
        <button class="gen-act play" @click="resetHere(true)">↻ neu generieren</button>
        <button class="gen-act danger" :class="{ armed: confirm === 'reset' }" @click="arm('reset', () => resetHere(false))">{{ confirm === 'reset' ? 'Sure?' : '✕ nur zurücksetzen' }}</button>
        <button class="gen-act ghost" @click="sel = null; confirm = null">Abbrechen</button>
      </div>
    </section>

    <section class="gen-section">
      <GuideBoardSection
        :topic="topic"
        :format="guideFormat"
        :refresh="guideRefresh"
        @cancelGuide="(id) => emit('cancelGuide', id)"
        @startGuide="(p) => emit('startGuide', p)"
        @resetStage="(p) => emit('resetGuideStage', p)"
        @preview="emit('preview')"
        @removeFormat="(f) => emit('removeFormat', f)"
        @resetCard="(p) => emit('resetGuideCard', p)"
      />
    </section>
  </div>
</template>

<style scoped>
.gen-view {
  flex: 1;
  min-width: 0;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  background: var(--bg-preview);
}
.gen-head {
  position: sticky;
  top: 0;
  z-index: 3;
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 1.25rem 2rem;
  border-bottom: 1px solid var(--border);
  background: var(--panel);
}
.gen-head h1 { font-size: 1.5rem; }
.gen-sub { color: var(--text-faint); font-size: 0.9rem; font-weight: 600; }
.gen-spacer { flex: 1; }
.gen-close {
  align-self: center;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: var(--panel);
  color: var(--text);
  width: 2rem;
  height: 2rem;
  cursor: pointer;
}
.gen-close:hover { border-color: var(--accent); }

.gen-section {
  padding: 0.85rem 2rem;
  border-bottom: 1px solid var(--border);
  background: var(--panel-soft);
}
.gen-title { font-size: 0.9rem; font-weight: 700; }
.gen-board-label {
  font-size: 0.64rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-faint);
  margin: 0.5rem 0 0.3rem;
}
.gen-progress {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.84rem;
  color: var(--accent);
  font-weight: 600;
}
.gen-progress-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  animation: gen-pulse 1.2s ease-in-out infinite;
}
@keyframes gen-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

.gen-steps-top { display: flex; align-items: center; gap: 1rem; min-height: 1.9rem; margin-bottom: 0.4rem; }
.gen-actions { margin-left: auto; display: flex; gap: 0.4rem; }

.gen-step-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.75rem;
  padding-top: 0.7rem;
  border-top: 1px dashed var(--border-strong);
}
.gen-step-actions-label { font-size: 0.8rem; font-weight: 600; color: var(--text-muted); }

.gen-act {
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: var(--panel);
  color: var(--text);
  font-size: 0.8rem;
  padding: 0.3rem 0.7rem;
  cursor: pointer;
  font-weight: 600;
}
.gen-act:hover { border-color: var(--accent); }
.gen-act.play { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.gen-act.play:hover { background: var(--accent-hover); }
.gen-act.danger { color: var(--danger); border-color: var(--danger); background: transparent; }
.gen-act.danger.armed { background: var(--danger); color: #fff; }
.gen-act.ghost { color: var(--text-muted); }
.qa-note {
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
}
.qa-note.ok { background: color-mix(in srgb, #22c55e 18%, transparent); color: #16a34a; }
.qa-note.bad { background: color-mix(in srgb, #ef4444 18%, transparent); color: #dc2626; }
.repair-info { font-size: 0.78rem; color: var(--text-muted); }
.qa-pause {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  padding: 0.5rem 0.8rem;
  margin-bottom: 0.8rem;
  border: 1px solid color-mix(in srgb, #ef4444 40%, transparent);
  border-radius: 8px;
  background: color-mix(in srgb, #ef4444 8%, transparent);
  font-size: 0.85rem;
}
</style>
