// ── Constants ─────────────────────────────────────────────────────────────────
const MAX_RECORD_SECONDS = 30;
const MAX_RECORD_WORDS   = 60;
const EXT_MAP = { 'audio/webm': 'webm', 'audio/ogg': 'ogg', 'audio/mp4': 'm4a', 'audio/mpeg': 'mp3' };

// ── State ─────────────────────────────────────────────────────────────────────
const state = {
  level: 'B1',
  currentTopic: null,
  currentIndex: 0,
  questionQueue: [],
  transcript: '',
  finalTranscript: '',
  isRecording: false,
  isChecking: false,
  sessionHistory: [],
};

// ── DOM refs ──────────────────────────────────────────────────────────────────
const screens = {
  topics:   document.getElementById('screen-topics'),
  practice: document.getElementById('screen-practice'),
  done:     document.getElementById('screen-done'),
};

const topicGrid      = document.getElementById('topic-grid');
const topicLabel     = document.getElementById('topic-label');
const progressFill   = document.getElementById('progress-fill');
const progressText   = document.getElementById('progress-text');
const questionText   = document.getElementById('question-text');
const transcriptBox  = document.getElementById('transcript-box');
const feedbackBox    = document.getElementById('feedback-box');
const feedbackContent= document.getElementById('feedback-content');
const recordBtn      = document.getElementById('record-btn');
const recordHint     = document.getElementById('record-hint');
const speakBtn       = document.getElementById('speak-btn');
const checkBtn       = document.getElementById('check-btn');
const clearBtn       = document.getElementById('clear-btn');
const downloadBtn    = document.getElementById('download-btn');
const skipBtn        = document.getElementById('skip-btn');
const nextActions    = document.getElementById('next-actions');
const nextBtn        = document.getElementById('next-btn');
const backBtn        = document.getElementById('back-btn');
const historySection = document.getElementById('history-section');
const historyList    = document.getElementById('history-list');

// ── About modal ───────────────────────────────────────────────────────────────
const aboutModal = document.getElementById('about-modal');
document.getElementById('about-btn').addEventListener('click', () => aboutModal.classList.add('open'));
document.getElementById('about-close').addEventListener('click', () => aboutModal.classList.remove('open'));
aboutModal.addEventListener('click', e => { if (e.target === aboutModal) aboutModal.classList.remove('open'); });

// ── Navigation ────────────────────────────────────────────────────────────────
function showScreen(name) {
  Object.values(screens).forEach(s => s.classList.remove('active'));
  screens[name].classList.add('active');
}

// ── Level selector ────────────────────────────────────────────────────────────
document.querySelectorAll('.level-btn').forEach(btn => {
  btn.addEventListener('click', () => {
    document.querySelectorAll('.level-btn').forEach(b => b.classList.remove('active'));
    btn.classList.add('active');
    state.level = btn.dataset.level;
  });
});

// ── Topic grid ────────────────────────────────────────────────────────────────
function buildTopicGrid() {
  TOPICS.forEach(topic => {
    const card = document.createElement('div');
    card.className = 'topic-card';
    card.innerHTML = `<div class="topic-icon">${topic.icon}</div><h3>${topic.name}</h3><p>${topic.desc}</p>`;
    card.addEventListener('click', () => startTopic(topic));
    topicGrid.appendChild(card);
  });
}

function startTopic(topic) {
  state.currentTopic = topic;
  state.sessionHistory = [];
  const indices = topic.questions.map((_, i) => i);
  for (let i = indices.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [indices[i], indices[j]] = [indices[j], indices[i]];
  }
  state.questionQueue = indices;
  renderHistoryList();
  showScreen('practice');
  loadQuestion();
}

// ── Questions ─────────────────────────────────────────────────────────────────
function loadQuestion() {
  const topic = state.currentTopic;
  state.currentIndex = state.questionQueue[0];
  const total = topic.questions.length;
  const done  = total - state.questionQueue.length;

  topicLabel.textContent       = `${topic.icon} ${topic.name}`;
  progressFill.style.width     = `${(done / total) * 100}%`;
  progressText.textContent     = `${done + 1} / ${total}`;
  questionText.textContent     = topic.questions[state.currentIndex];

  resetPracticeUI();
  autoSpeak();
}

function resetPracticeUI() {
  state.transcript = '';
  state.finalTranscript = '';
  transcriptBox.contentEditable = 'false';
  updateTranscriptBox('');
  feedbackBox.classList.remove('visible');
  feedbackContent.innerHTML = '';
  nextActions.style.display = 'none';
  checkBtn.disabled    = true;
  skipBtn.disabled     = false;
  downloadBtn.disabled = true;
  audioBlob = null;
  stopRecording(true);
}

// ── Audio playback ────────────────────────────────────────────────────────────
let audioPlayer = null;

function stopAudio() {
  if (audioPlayer) { audioPlayer.pause(); audioPlayer = null; }
  speakBtn.classList.remove('speaking');
}

function autoSpeak() {
  stopAudio();
  const { id } = state.currentTopic;
  audioPlayer = new Audio(`audio/${id}_${state.currentIndex}.mp3`);
  speakBtn.classList.add('speaking');
  audioPlayer.onended = stopAudio;
  audioPlayer.onerror = stopAudio;
  audioPlayer.play();
}

speakBtn.addEventListener('click', () => {
  if (audioPlayer && !audioPlayer.paused) { stopAudio(); return; }
  autoSpeak();
});

// ── MediaRecorder → Whisper ───────────────────────────────────────────────────
let recordingTimer = null;
let mediaRecorder  = null;
let audioChunks    = [];
let audioBlob      = null;
let _discardNext   = false; // set to true when stopping without intent to transcribe

async function startRecording() {
  stopAudio();
  _discardNext = false;
  audioBlob    = null;
  audioChunks  = [];
  downloadBtn.disabled = true;
  transcriptBox.contentEditable = 'false';

  try {
    const stream   = await navigator.mediaDevices.getUserMedia({ audio: true });
    const mimeType = MediaRecorder.isTypeSupported('audio/webm;codecs=opus') ? 'audio/webm;codecs=opus'
                   : MediaRecorder.isTypeSupported('audio/webm')             ? 'audio/webm'
                   : MediaRecorder.isTypeSupported('audio/mp4')              ? 'audio/mp4'
                   : '';
    mediaRecorder = new MediaRecorder(stream, mimeType ? { mimeType } : {});
    mediaRecorder.ondataavailable = e => { if (e.data.size > 0) audioChunks.push(e.data); };
    mediaRecorder.onstop = async () => {
      stream.getTracks().forEach(t => t.stop());
      if (_discardNext) { _discardNext = false; return; }
      const blob = new Blob(audioChunks, { type: mimeType || 'audio/webm' });
      audioBlob = blob;
      if (blob.size > 0) downloadBtn.disabled = false;
      await transcribeAudio(blob);
    };
    mediaRecorder.start();
  } catch (err) {
    alert('Mikrofon nicht verfügbar: ' + err.message);
    return;
  }

  state.isRecording = true;
  recordBtn.classList.add('recording');
  recordHint.textContent = 'Tippen zum Stoppen';

  // Show listening indicator — not editable, no interim text
  transcriptBox.textContent = 'Ich höre zu…';
  transcriptBox.classList.remove('empty');

  clearTimeout(recordingTimer);
  recordingTimer = setTimeout(stopRecording, MAX_RECORD_SECONDS * 1000);
}

function stopRecording(discard = false) {
  clearTimeout(recordingTimer);
  state.isRecording = false;
  if (discard) _discardNext = true;
  if (mediaRecorder && mediaRecorder.state !== 'inactive') {
    mediaRecorder.stop(); // onstop fires → transcribeAudio (unless _discardNext)
    mediaRecorder = null;
  }
  recordBtn.classList.remove('recording');
  if (discard) {
    recordHint.textContent = 'Tippen zum Aufnehmen';
    transcriptBox.contentEditable = 'true';
  }
  // When not discarding: UI updated inside transcribeAudio after server responds
}

async function transcribeAudio(blob) {
  recordBtn.disabled = true;
  recordHint.textContent = 'Transkribiere…';
  transcriptBox.textContent = 'Transkribiere…';
  transcriptBox.classList.remove('empty');

  try {
    const res  = await authFetch('api/transcribe', {
      method:  'POST',
      headers: { 'Content-Type': blob.type || 'audio/webm' },
      body:    blob,
    });
    const data = await res.json();
    if (!res.ok) throw new Error(data.error || 'Fehler');

    const text = (data.transcript || '').trim();
    state.transcript      = text;
    state.finalTranscript = text;
    updateTranscriptBox(text);
    checkBtn.disabled = !text;
    transcriptBox.contentEditable = 'true';
  } catch (err) {
    console.error('Transcription failed:', err);
    updateTranscriptBox('');
    recordHint.textContent = 'Fehler – nochmal versuchen';
  } finally {
    recordBtn.disabled = false;
    recordHint.textContent = 'Tippen zum Aufnehmen';
  }
}

recordBtn.addEventListener('click', () => state.isRecording ? stopRecording() : startRecording());

// ── Transcript box ────────────────────────────────────────────────────────────
function updateTranscriptBox(text) {
  transcriptBox.textContent = text;
  transcriptBox.classList.toggle('empty', !text);
}

transcriptBox.addEventListener('input', () => {
  state.transcript = transcriptBox.textContent.trim();
  checkBtn.disabled = !state.transcript;
});

// ── Download recording ────────────────────────────────────────────────────────
downloadBtn.addEventListener('click', () => {
  if (!audioBlob) return;
  const topic    = (state.currentTopic?.name || 'antwort').replace(/[^\w]/g, '_');
  const now      = new Date();
  const ext      = EXT_MAP[audioBlob.type.split(';')[0]] || 'webm';
  const ms5 = String(Date.now()).slice(-5);
  const filename = `${topic}_q${state.currentIndex + 1}_${now.getDate()}-${now.getMonth() + 1}_${ms5}.${ext}`;
  const url = URL.createObjectURL(audioBlob);
  const a = document.createElement('a');
  a.href = url; a.download = filename; a.click();
  URL.revokeObjectURL(url);
});

// ── Clear ─────────────────────────────────────────────────────────────────────
clearBtn.addEventListener('click', () => {
  stopRecording(true);
  state.transcript = '';
  state.finalTranscript = '';
  transcriptBox.contentEditable = 'false';
  updateTranscriptBox('');
  checkBtn.disabled = true;
  feedbackBox.classList.remove('visible');
  nextActions.style.display = 'none';
});

// ── Check answer ──────────────────────────────────────────────────────────────
checkBtn.addEventListener('click', async () => {
  const answer = state.transcript.trim();
  if (!answer || state.isChecking) return;

  stopRecording(true);
  state.isChecking = true;
  checkBtn.disabled = true;
  feedbackBox.classList.add('visible');
  feedbackContent.innerHTML = '<div class="loading-dots"><span></span><span></span><span></span></div>';

  try {
    const res  = await authFetch('api/check', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        question: state.currentTopic.questions[state.currentIndex],
        answer,
        level: state.level,
      }),
    });
    const data = await res.json();
    if (!res.ok) throw new Error(data.error || 'Fehler');

    feedbackContent.innerHTML = simpleMarkdown(data.feedback || '');
    state.sessionHistory.push({ question: state.currentTopic.questions[state.currentIndex], answer, feedback: data.feedback });
    renderHistoryList();
  } catch (err) {
    feedbackContent.innerHTML = `<span style="color:var(--danger)">Fehler: ${err.message}</span>`;
  } finally {
    state.isChecking = false;
    nextActions.style.display = 'flex';
    skipBtn.disabled = true;
  }
});

// ── Markdown renderer ─────────────────────────────────────────────────────────
function simpleMarkdown(text) {
  return text
    .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
    .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
    .replace(/\*(.+?)\*/g,     '<em>$1</em>')
    .replace(/`(.+?)`/g,       '<code>$1</code>')
    .replace(/^#{1,3} (.+)$/gm,'<h3>$1</h3>')
    .replace(/^\d+\. (.+)$/gm, '<li>$1</li>')
    .replace(/^[-•] (.+)$/gm,  '<li>$1</li>')
    .replace(/(<li>.*<\/li>\n?)+/g, m => `<ul>${m}</ul>`)
    .replace(/\n{2,}/g, '</p><p>')
    .replace(/\n/g, '<br>')
    .replace(/^(.+)$/, '<p>$1</p>');
}

// ── Skip / Retry / Next / Done ────────────────────────────────────────────────
skipBtn.addEventListener('click', () => {
  stopRecording(true); stopAudio();
  state.questionQueue.shift();
  state.questionQueue.length === 0 ? showDone() : loadQuestion();
});

document.getElementById('retry-btn').addEventListener('click', () => { resetPracticeUI(); autoSpeak(); });

nextBtn.addEventListener('click', () => {
  state.questionQueue.shift();
  state.questionQueue.length === 0 ? showDone() : loadQuestion();
});

function showDone() {
  document.getElementById('stat-answered').textContent = state.sessionHistory.length;
  document.getElementById('stat-level').textContent    = state.level;
  progressFill.style.width = '100%';
  showScreen('done');
}

backBtn.addEventListener('click', () => { stopRecording(true); stopAudio(); showScreen('topics'); });
document.getElementById('restart-btn').addEventListener('click', () => showScreen('topics'));

// ── History ───────────────────────────────────────────────────────────────────
function renderHistoryList() {
  historySection.classList.toggle('has-items', state.sessionHistory.length > 0);
  historyList.innerHTML = '';
  [...state.sessionHistory].reverse().forEach(item => {
    const el = document.createElement('div');
    el.className = 'history-item';
    el.innerHTML = `<div class="hi-q">F: ${escapeHtml(item.question)}</div><div class="hi-a">A: ${escapeHtml(item.answer)}</div>`;
    el.addEventListener('click', () => {
      feedbackContent.innerHTML = simpleMarkdown(item.feedback);
      feedbackBox.classList.add('visible');
      feedbackBox.scrollIntoView({ behavior: 'smooth', block: 'start' });
    });
    historyList.appendChild(el);
  });
}

function escapeHtml(s) {
  return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}

// ── Init ──────────────────────────────────────────────────────────────────────
buildTopicGrid();
