"""
BreakPilot Studio - Klausurkorrektur Modul

Funktionen:
- Klausuren hochladen (PDF/Bilder)
- OCR-Verarbeitung
- Automatische Bewertung mit AI
- Pipeline-Visualisierung
- Review-Interface
- Export (PDF/CSV/Excel)
"""


class CorrectionModule:
    """Modul fuer Klausurkorrektur mit OCR und AI-Bewertung."""

    @staticmethod
    def get_css() -> str:
        """CSS fuer das Correction-Modul."""
        return """
/* =============================================
   CORRECTION MODULE - Klausurkorrektur
   ============================================= */

/* Panel Layout */
.panel-correction {
  display: none;
  flex-direction: column;
  height: 100%;
  background: var(--bg-primary);
}

.panel-correction.active {
  display: flex;
}

/* Header */
.correction-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 24px;
  border-bottom: 1px solid var(--border-color);
  background: var(--bg-secondary);
}

.correction-title {
  font-size: 18px;
  font-weight: 600;
  color: var(--text-primary);
}

.correction-actions {
  display: flex;
  gap: 12px;
}

/* Content Layout */
.correction-content {
  display: flex;
  flex: 1;
  overflow: hidden;
}

/* Linke Spalte - Setup */
.correction-setup-panel {
  width: 320px;
  border-right: 1px solid var(--border-color);
  display: flex;
  flex-direction: column;
  background: var(--bg-secondary);
  overflow-y: auto;
}

.correction-section {
  padding: 20px;
  border-bottom: 1px solid var(--border-color);
}

.correction-section h3 {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-secondary);
  margin-bottom: 16px;
}

/* Upload Area */
.correction-upload-area {
  border: 2px dashed var(--border-color);
  border-radius: 12px;
  padding: 32px 24px;
  text-align: center;
  cursor: pointer;
  transition: all 0.2s;
  background: var(--bg-primary);
}

.correction-upload-area:hover {
  border-color: var(--accent-primary);
  background: rgba(59, 130, 246, 0.05);
}

.correction-upload-area.dragover {
  border-color: var(--accent-primary);
  background: rgba(59, 130, 246, 0.1);
}

.correction-upload-area .upload-icon {
  font-size: 48px;
  margin-bottom: 16px;
}

.correction-upload-area h3 {
  margin-bottom: 8px;
  color: var(--text-primary);
}

.correction-upload-area p {
  color: var(--text-secondary);
  font-size: 13px;
}

.correction-upload-area .file-types {
  margin-top: 12px;
  font-size: 11px;
  color: var(--text-tertiary);
}

/* Form Fields */
.correction-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.correction-form label {
  font-size: 12px;
  color: var(--text-secondary);
  margin-bottom: 4px;
}

.correction-form input,
.correction-form select {
  padding: 10px 12px;
  border: 1px solid var(--border-color);
  border-radius: 8px;
  background: var(--bg-primary);
  color: var(--text-primary);
  font-size: 13px;
}

.correction-form input:focus,
.correction-form select:focus {
  outline: none;
  border-color: var(--accent-primary);
}

.correction-form .form-group {
  display: flex;
  flex-direction: column;
}

.correction-form .form-row {
  display: flex;
  gap: 12px;
}

.correction-form .form-row .form-group {
  flex: 1;
}

/* Start Button */
.correction-start-btn {
  padding: 14px 24px;
  background: var(--accent-primary);
  color: white;
  border: none;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s;
  margin-top: 8px;
}

.correction-start-btn:hover:not(:disabled) {
  background: var(--accent-hover);
  transform: translateY(-1px);
}

.correction-start-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Mittlere Spalte - Pipeline */
.correction-pipeline-panel {
  width: 200px;
  border-right: 1px solid var(--border-color);
  padding: 24px 16px;
  background: var(--bg-primary);
}

.pipeline-title {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 20px;
}

.pipeline-steps {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.pipeline-step {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  border-radius: 8px;
  background: var(--bg-secondary);
  transition: all 0.3s;
}

.pipeline-step-icon {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-tertiary);
  color: var(--text-tertiary);
  font-size: 14px;
  transition: all 0.3s;
}

.pipeline-step-content {
  flex: 1;
}

.pipeline-step-label {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-primary);
}

.pipeline-step-status {
  font-size: 11px;
  color: var(--text-tertiary);
}

.pipeline-step.active {
  background: rgba(59, 130, 246, 0.1);
}

.pipeline-step.active .pipeline-step-icon {
  background: var(--accent-primary);
  color: white;
  animation: pulse 1.5s infinite;
}

.pipeline-step.completed .pipeline-step-icon {
  background: #10b981;
  color: white;
}

.pipeline-step.error .pipeline-step-icon {
  background: #ef4444;
  color: white;
}

@keyframes pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.05); opacity: 0.8; }
}

/* Rechte Spalte - Results/Review */
.correction-results-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.results-header {
  padding: 16px 24px;
  border-bottom: 1px solid var(--border-color);
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: var(--bg-secondary);
}

.results-title {
  font-size: 16px;
  font-weight: 600;
}

.results-stats {
  display: flex;
  gap: 24px;
}

.stat-item {
  text-align: center;
}

.stat-value {
  font-size: 24px;
  font-weight: 700;
  color: var(--accent-primary);
}

.stat-label {
  font-size: 11px;
  color: var(--text-tertiary);
  text-transform: uppercase;
}

/* Results Content */
.correction-results {
  flex: 1;
  overflow-y: auto;
  padding: 24px;
}

.results-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--text-tertiary);
}

.results-placeholder .icon {
  font-size: 64px;
  margin-bottom: 16px;
  opacity: 0.5;
}

.results-placeholder h3 {
  margin-bottom: 8px;
  color: var(--text-secondary);
}

/* Exam List */
.exam-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.exam-item {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px;
  background: var(--bg-secondary);
  border-radius: 12px;
  border: 1px solid var(--border-color);
  cursor: pointer;
  transition: all 0.2s;
}

.exam-item:hover {
  border-color: var(--accent-primary);
  transform: translateX(4px);
}

.exam-item.active {
  border-color: var(--accent-primary);
  background: rgba(59, 130, 246, 0.05);
}

.exam-thumb {
  width: 60px;
  height: 80px;
  border-radius: 6px;
  background: var(--bg-tertiary);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.exam-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.exam-info {
  flex: 1;
}

.exam-name {
  font-weight: 500;
  margin-bottom: 4px;
}

.exam-meta {
  font-size: 12px;
  color: var(--text-secondary);
}

.exam-grade {
  padding: 8px 16px;
  border-radius: 20px;
  font-weight: 600;
  font-size: 14px;
}

.exam-grade.excellent {
  background: rgba(16, 185, 129, 0.1);
  color: #10b981;
}

.exam-grade.good {
  background: rgba(59, 130, 246, 0.1);
  color: #3b82f6;
}

.exam-grade.average {
  background: rgba(245, 158, 11, 0.1);
  color: #f59e0b;
}

.exam-grade.poor {
  background: rgba(239, 68, 68, 0.1);
  color: #ef4444;
}

/* Review Interface */
.review-interface {
  display: none;
  flex: 1;
  overflow: hidden;
}

.review-interface.active {
  display: flex;
}

.review-left {
  flex: 1;
  border-right: 1px solid var(--border-color);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.review-image-container {
  flex: 1;
  overflow: auto;
  padding: 16px;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  background: var(--bg-tertiary);
}

.review-image {
  max-width: 100%;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}

.review-right {
  width: 400px;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

.review-section {
  padding: 20px;
  border-bottom: 1px solid var(--border-color);
}

.review-section-title {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-tertiary);
  text-transform: uppercase;
  margin-bottom: 12px;
}

/* OCR Text */
.ocr-text-container {
  background: var(--bg-primary);
  border: 1px solid var(--border-color);
  border-radius: 8px;
  padding: 16px;
  font-family: 'Monaco', 'Consolas', monospace;
  font-size: 13px;
  line-height: 1.6;
  max-height: 200px;
  overflow-y: auto;
}

/* Answer Sections */
.answer-section {
  background: var(--bg-primary);
  border: 1px solid var(--border-color);
  border-radius: 8px;
  padding: 16px;
  margin-bottom: 12px;
}

.answer-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.answer-task {
  font-weight: 600;
}

.answer-points {
  display: flex;
  align-items: center;
  gap: 8px;
}

.answer-points input {
  width: 50px;
  padding: 6px 8px;
  border: 1px solid var(--border-color);
  border-radius: 6px;
  text-align: center;
  font-weight: 600;
  background: var(--bg-secondary);
  color: var(--text-primary);
}

.answer-text {
  font-size: 13px;
  color: var(--text-secondary);
  margin-bottom: 12px;
  padding: 12px;
  background: var(--bg-secondary);
  border-radius: 6px;
}

.ai-feedback {
  font-size: 12px;
  color: var(--text-tertiary);
  padding: 10px;
  background: rgba(59, 130, 246, 0.05);
  border-left: 3px solid var(--accent-primary);
  border-radius: 0 6px 6px 0;
}

/* Total Score */
.total-score-section {
  padding: 20px;
  background: var(--bg-secondary);
}

.total-score {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  background: var(--bg-primary);
  border-radius: 12px;
}

.total-score-label {
  font-size: 14px;
  color: var(--text-secondary);
}

.total-score-value {
  font-size: 28px;
  font-weight: 700;
  color: var(--accent-primary);
}

.grade-select {
  padding: 10px 16px;
  font-size: 18px;
  font-weight: 600;
  border: 2px solid var(--accent-primary);
  border-radius: 8px;
  background: var(--bg-primary);
  color: var(--accent-primary);
  cursor: pointer;
}

/* Review Actions */
.review-actions {
  display: flex;
  gap: 12px;
  padding: 16px;
  border-top: 1px solid var(--border-color);
  background: var(--bg-secondary);
}

.review-actions .btn {
  flex: 1;
}

/* Export Options */
.export-options {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.export-btn {
  padding: 8px 16px;
  border: 1px solid var(--border-color);
  border-radius: 6px;
  background: var(--bg-primary);
  color: var(--text-primary);
  font-size: 12px;
  cursor: pointer;
  transition: all 0.2s;
}

.export-btn:hover {
  background: var(--bg-hover);
  border-color: var(--accent-primary);
}

.export-btn .icon {
  margin-right: 6px;
}

/* Empty State */
.correction-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 48px;
  text-align: center;
}

.correction-empty .icon {
  font-size: 80px;
  margin-bottom: 24px;
  opacity: 0.3;
}

.correction-empty h2 {
  margin-bottom: 12px;
  color: var(--text-secondary);
}

.correction-empty p {
  color: var(--text-tertiary);
  max-width: 400px;
}
"""

    @staticmethod
    def get_html() -> str:
        """HTML fuer das Correction-Modul."""
        return """
<!-- Correction Panel -->
<div id="panel-correction" class="panel-correction">
  <!-- Header -->
  <div class="correction-header">
    <div class="correction-title">Klausurkorrektur</div>
    <div class="correction-actions">
      <div class="export-options">
        <button class="export-btn" onclick="exportCorrectionResults('pdf')">
          <span class="icon">📄</span>PDF
        </button>
        <button class="export-btn" onclick="exportCorrectionResults('csv')">
          <span class="icon">📊</span>CSV
        </button>
        <button class="export-btn" onclick="exportCorrectionResults('excel')">
          <span class="icon">📗</span>Excel
        </button>
      </div>
    </div>
  </div>

  <!-- Content -->
  <div class="correction-content">
    <!-- Linke Spalte: Setup -->
    <div class="correction-setup-panel">
      <!-- Upload Section -->
      <div class="correction-section">
        <h3>Klausuren hochladen</h3>
        <div class="correction-upload-area" id="exam-upload-area">
          <div class="upload-icon">📝</div>
          <h3>Klausuren hochladen</h3>
          <p>Dateien hierher ziehen oder klicken</p>
          <div class="file-types">PDF, JPG, PNG - max. 50MB</div>
          <input type="file" id="exam-file-input" multiple accept=".pdf,.jpg,.jpeg,.png" hidden>
        </div>
      </div>

      <!-- Exam Info -->
      <div class="correction-section">
        <h3>Klausur-Informationen</h3>
        <div class="correction-form">
          <div class="form-group">
            <label>Fach</label>
            <select id="exam-subject">
              <option value="">Fach waehlen...</option>
              <option value="deutsch">Deutsch</option>
              <option value="mathe">Mathematik</option>
              <option value="englisch">Englisch</option>
              <option value="physik">Physik</option>
              <option value="chemie">Chemie</option>
              <option value="biologie">Biologie</option>
              <option value="geschichte">Geschichte</option>
              <option value="erdkunde">Erdkunde</option>
              <option value="andere">Andere</option>
            </select>
          </div>
          <div class="form-row">
            <div class="form-group">
              <label>Klasse</label>
              <input type="text" id="exam-class" placeholder="z.B. 10a">
            </div>
            <div class="form-group">
              <label>Max. Punkte</label>
              <input type="number" id="exam-max-points" placeholder="100" value="100">
            </div>
          </div>
          <div class="form-group">
            <label>Titel/Thema</label>
            <input type="text" id="exam-title" placeholder="z.B. Klassenarbeit Nr. 3">
          </div>
        </div>
      </div>

      <!-- Start Button -->
      <div class="correction-section">
        <button class="correction-start-btn" id="start-correction-btn" disabled onclick="startCorrectionJob()">
          Korrektur starten
        </button>
      </div>
    </div>

    <!-- Mittlere Spalte: Pipeline -->
    <div class="correction-pipeline-panel">
      <div class="pipeline-title">Verarbeitungs-Pipeline</div>
      <div class="pipeline-steps">
        <div class="pipeline-step" data-step="upload">
          <div class="pipeline-step-icon">📤</div>
          <div class="pipeline-step-content">
            <div class="pipeline-step-label">Upload</div>
            <div class="pipeline-step-status">Dateien hochladen</div>
          </div>
        </div>
        <div class="pipeline-step" data-step="preprocess">
          <div class="pipeline-step-icon">🔧</div>
          <div class="pipeline-step-content">
            <div class="pipeline-step-label">Vorverarbeitung</div>
            <div class="pipeline-step-status">Bildoptimierung</div>
          </div>
        </div>
        <div class="pipeline-step" data-step="ocr">
          <div class="pipeline-step-icon">👁️</div>
          <div class="pipeline-step-content">
            <div class="pipeline-step-label">OCR</div>
            <div class="pipeline-step-status">Texterkennung</div>
          </div>
        </div>
        <div class="pipeline-step" data-step="segment">
          <div class="pipeline-step-icon">✂️</div>
          <div class="pipeline-step-content">
            <div class="pipeline-step-label">Segmentierung</div>
            <div class="pipeline-step-status">Aufgaben erkennen</div>
          </div>
        </div>
        <div class="pipeline-step" data-step="grade">
          <div class="pipeline-step-icon">🤖</div>
          <div class="pipeline-step-content">
            <div class="pipeline-step-label">AI-Bewertung</div>
            <div class="pipeline-step-status">Automatisch benoten</div>
          </div>
        </div>
        <div class="pipeline-step" data-step="review">
          <div class="pipeline-step-icon">✅</div>
          <div class="pipeline-step-content">
            <div class="pipeline-step-label">Review</div>
            <div class="pipeline-step-status">Ueberpruefen</div>
          </div>
        </div>
      </div>
    </div>

    <!-- Rechte Spalte: Results -->
    <div class="correction-results-panel">
      <div class="results-header">
        <div class="results-title">Ergebnisse</div>
        <div class="results-stats">
          <div class="stat-item">
            <div class="stat-value" id="stat-total">0</div>
            <div class="stat-label">Klausuren</div>
          </div>
          <div class="stat-item">
            <div class="stat-value" id="stat-corrected">0</div>
            <div class="stat-label">Korrigiert</div>
          </div>
          <div class="stat-item">
            <div class="stat-value" id="stat-average">-</div>
            <div class="stat-label">Durchschnitt</div>
          </div>
        </div>
      </div>

      <!-- Results/Review Content -->
      <div class="correction-results" id="correction-results">
        <div class="correction-empty">
          <div class="icon">📝</div>
          <h2>Keine Klausuren geladen</h2>
          <p>Lade Klausuren hoch und starte die automatische Korrektur, um Ergebnisse zu sehen.</p>
        </div>
      </div>

      <!-- Review Interface (hidden by default) -->
      <div class="review-interface" id="review-interface">
        <div class="review-left">
          <div class="review-image-container">
            <img id="review-image" class="review-image" src="" alt="Klausur">
          </div>
        </div>
        <div class="review-right">
          <!-- OCR Text -->
          <div class="review-section">
            <div class="review-section-title">Erkannter Text (OCR)</div>
            <div class="ocr-text-container" id="ocr-text">
              Hier erscheint der erkannte Text...
            </div>
          </div>

          <!-- Answers -->
          <div class="review-section">
            <div class="review-section-title">Antworten & Bewertung</div>
            <div id="answers-container">
              <!-- Wird dynamisch gefuellt -->
            </div>
          </div>

          <!-- Total Score -->
          <div class="total-score-section">
            <div class="total-score">
              <div>
                <div class="total-score-label">Gesamtpunkte</div>
                <div class="total-score-value" id="total-points">0 / 100</div>
              </div>
              <select class="grade-select" id="grade-select">
                <option value="1">1</option>
                <option value="2">2</option>
                <option value="3">3</option>
                <option value="4">4</option>
                <option value="5">5</option>
                <option value="6">6</option>
              </select>
            </div>
          </div>

          <!-- Review Actions -->
          <div class="review-actions">
            <button class="btn btn-secondary" onclick="previousExam()">Zurueck</button>
            <button class="btn btn-primary" onclick="saveAndNextExam()">Speichern & Weiter</button>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
"""

    @staticmethod
    def get_js() -> str:
        """JavaScript fuer das Correction-Modul."""
        return """
// =============================================
// CORRECTION MODULE - Klausurkorrektur
// =============================================

let correctionInitialized = false;
let currentExamJob = null;
let examUploadedFiles = [];
let correctedExams = [];
let currentExamIndex = 0;

function loadCorrectionModule() {
  if (correctionInitialized) {
    console.log('Correction module already initialized');
    return;
  }

  console.log('Loading Correction Module...');

  // DOM Elements
  const uploadArea = document.getElementById('exam-upload-area');
  const fileInput = document.getElementById('exam-file-input');
  const startBtn = document.getElementById('start-correction-btn');
  const resultsContainer = document.getElementById('correction-results');
  const reviewInterface = document.getElementById('review-interface');

  // --- Upload Handler ---
  if (uploadArea && fileInput) {
    uploadArea.addEventListener('click', () => fileInput.click());

    uploadArea.addEventListener('dragover', (ev) => {
      ev.preventDefault();
      uploadArea.classList.add('dragover');
    });

    uploadArea.addEventListener('dragleave', () => {
      uploadArea.classList.remove('dragover');
    });

    uploadArea.addEventListener('drop', (ev) => {
      ev.preventDefault();
      uploadArea.classList.remove('dragover');
      handleExamFiles(ev.dataTransfer.files);
    });

    fileInput.addEventListener('change', () => {
      handleExamFiles(fileInput.files);
    });
  }

  correctionInitialized = true;
  console.log('Correction Module loaded successfully');
}

// Handle exam file upload
function handleExamFiles(files) {
  if (!files.length) return;

  examUploadedFiles = Array.from(files);
  console.log(`${examUploadedFiles.length} Dateien fuer Klausur-Korrektur ausgewaehlt`);

  // Update UI
  const uploadArea = document.getElementById('exam-upload-area');
  if (uploadArea) {
    uploadArea.innerHTML = `
      <div style="color: #10b981; font-size: 48px;">✓</div>
      <h3>${examUploadedFiles.length} Datei(en) ausgewaehlt</h3>
      <p>${examUploadedFiles.map(f => f.name).slice(0, 3).join(', ')}${examUploadedFiles.length > 3 ? '...' : ''}</p>
      <button onclick="document.getElementById('exam-file-input').click()"
              style="margin-top: 16px; padding: 8px 16px; background: var(--bg-tertiary); border: none; border-radius: 8px; color: var(--text-primary); cursor: pointer;">
        Andere Dateien waehlen
      </button>
    `;
  }

  // Enable start button
  const startBtn = document.getElementById('start-correction-btn');
  if (startBtn) {
    startBtn.disabled = false;
  }

  // Update stats
  document.getElementById('stat-total').textContent = examUploadedFiles.length;
}

// Start correction job - connects to /api/corrections API
async function startCorrectionJob() {
  if (!examUploadedFiles.length) {
    alert('Bitte waehle zuerst Dateien aus.');
    return;
  }

  const subject = document.getElementById('exam-subject')?.value || 'unbekannt';
  const className = document.getElementById('exam-class')?.value || '';
  const title = document.getElementById('exam-title')?.value || 'Klausur';
  const maxPoints = parseInt(document.getElementById('exam-max-points')?.value) || 100;

  console.log('Starte Korrektur-Job:', { subject, className, title, files: examUploadedFiles.length });

  // Show pipeline progress
  updatePipelineStep('upload', 'active');

  // Reset state
  correctedExams = [];
  currentExamIndex = 0;

  try {
    // Process each file: create correction -> upload -> analyze
    for (let i = 0; i < examUploadedFiles.length; i++) {
      const file = examUploadedFiles[i];
      console.log(`Verarbeite Datei ${i + 1}/${examUploadedFiles.length}: ${file.name}`);

      // Step 1: Create correction entry
      const createResp = await fetch('/api/corrections/', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          student_id: `student-${i + 1}`,
          student_name: file.name.replace(/\\.[^.]+$/, ''), // Use filename as student name
          class_name: className,
          exam_title: title,
          subject: subject,
          max_points: maxPoints
        })
      });

      if (!createResp.ok) {
        throw new Error(`Korrektur erstellen fehlgeschlagen fuer ${file.name}`);
      }

      const createResult = await createResp.json();
      if (!createResult.success) {
        throw new Error(createResult.error || 'Korrektur erstellen fehlgeschlagen');
      }

      const correctionId = createResult.correction.id;
      updatePipelineStep('preprocess', 'active');
      updatePipelineStep('upload', 'completed');

      // Step 2: Upload file
      const formData = new FormData();
      formData.append('file', file);

      const uploadResp = await fetch(`/api/corrections/${correctionId}/upload`, {
        method: 'POST',
        body: formData
      });

      if (!uploadResp.ok) {
        throw new Error(`Upload fehlgeschlagen fuer ${file.name}`);
      }

      updatePipelineStep('ocr', 'active');
      updatePipelineStep('preprocess', 'completed');

      // Step 3: Poll for OCR completion
      let correction = await pollForOCRCompletion(correctionId);

      updatePipelineStep('segment', 'active');
      updatePipelineStep('ocr', 'completed');

      // Step 4: Analyze
      updatePipelineStep('grade', 'active');
      updatePipelineStep('segment', 'completed');

      const analyzeResp = await fetch(`/api/corrections/${correctionId}/analyze`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({})
      });

      if (analyzeResp.ok) {
        const analysisResult = await analyzeResp.json();
        if (analysisResult.success) {
          // Refresh correction data
          const getResp = await fetch(`/api/corrections/${correctionId}`);
          if (getResp.ok) {
            const getResult = await getResp.json();
            if (getResult.success) {
              correction = getResult.correction;
            }
          }
        }
      }

      // Add to results
      correctedExams.push({
        id: correction.id,
        filename: file.name,
        student_name: correction.student_name,
        points: correction.total_points,
        max_points: correction.max_points,
        percentage: correction.percentage,
        grade: correction.grade || _calculateLocalGrade(correction.percentage),
        ocr_text: correction.extracted_text || '',
        answers: (correction.evaluations || []).map((e, idx) => ({
          task: `Aufgabe ${e.question_number}`,
          points: e.points_awarded,
          max: e.points_possible,
          text: e.extracted_text,
          feedback: e.feedback
        })),
        image_url: correction.file_path ? `/static/corrections/${correction.id}` : null
      });

      // Update progress
      document.getElementById('stat-corrected').textContent = correctedExams.length;
    }

    // All done
    updatePipelineStep('review', 'active');
    updatePipelineStep('grade', 'completed');

    showCorrectionResults(correctedExams);

    updatePipelineStep('review', 'completed');

  } catch (e) {
    console.error('Korrektur-Job fehlgeschlagen:', e);
    alert('Korrektur fehlgeschlagen: ' + e.message);
    // Mark current step as error
    document.querySelectorAll('.pipeline-step.active').forEach(step => {
      step.classList.remove('active');
      step.classList.add('error');
    });
  }
}

// Poll for OCR completion
async function pollForOCRCompletion(correctionId, maxAttempts = 30) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    await new Promise(resolve => setTimeout(resolve, 1000)); // Wait 1 second

    const resp = await fetch(`/api/corrections/${correctionId}`);
    if (!resp.ok) continue;

    const result = await resp.json();
    if (!result.success) continue;

    const correction = result.correction;

    // Check status
    if (correction.status === 'ocr_complete' || correction.status === 'analyzed' || correction.status === 'completed') {
      return correction;
    }

    if (correction.status === 'error') {
      throw new Error('OCR-Verarbeitung fehlgeschlagen');
    }

    // Still processing, continue polling
  }

  throw new Error('OCR-Verarbeitung Timeout');
}

// Calculate grade locally (fallback)
function _calculateLocalGrade(percentage) {
  if (percentage >= 92) return '1';
  if (percentage >= 81) return '2';
  if (percentage >= 67) return '3';
  if (percentage >= 50) return '4';
  if (percentage >= 30) return '5';
  return '6';
}

// Reset pipeline visualization
function resetPipeline() {
  const steps = ['upload', 'preprocess', 'ocr', 'segment', 'grade', 'review'];
  steps.forEach(step => updatePipelineStep(step, null));
}

// Update pipeline step visualization
function updatePipelineStep(stepId, status) {
  const step = document.querySelector(`[data-step="${stepId}"]`);
  if (!step) return;

  step.classList.remove('active', 'completed', 'error');
  if (status) {
    step.classList.add(status);
  }
}

// Show correction results
function showCorrectionResults(results) {
  correctedExams = results || [];

  // Update stats
  document.getElementById('stat-corrected').textContent = correctedExams.length;
  const avg = correctedExams.length
    ? (correctedExams.reduce((sum, e) => sum + e.points, 0) / correctedExams.length).toFixed(1)
    : '-';
  document.getElementById('stat-average').textContent = avg;

  // Render exam list
  const container = document.getElementById('correction-results');
  if (!container) return;

  if (!correctedExams.length) {
    container.innerHTML = `
      <div class="correction-empty">
        <div class="icon">📝</div>
        <h2>Keine Ergebnisse</h2>
        <p>Die Korrektur wurde abgeschlossen, aber es wurden keine Ergebnisse gefunden.</p>
      </div>
    `;
    return;
  }

  container.innerHTML = `
    <div class="exam-list">
      ${correctedExams.map((exam, idx) => `
        <div class="exam-item${idx === currentExamIndex ? ' active' : ''}" onclick="selectExam(${idx})">
          <div class="exam-thumb">
            <span style="font-size: 24px;">📄</span>
          </div>
          <div class="exam-info">
            <div class="exam-name">${exam.student_name || exam.filename}</div>
            <div class="exam-meta">${exam.points} / ${exam.max_points} Punkte</div>
          </div>
          <div class="exam-grade ${getGradeClass(exam.grade)}">${exam.grade}</div>
        </div>
      `).join('')}
    </div>
  `;
}

// Get grade class for styling
function getGradeClass(grade) {
  const g = parseInt(grade);
  if (g === 1) return 'excellent';
  if (g === 2) return 'good';
  if (g === 3 || g === 4) return 'average';
  return 'poor';
}

// Select exam for review
function selectExam(index) {
  currentExamIndex = index;
  const exam = correctedExams[index];
  if (!exam) return;

  // Update active state in list
  document.querySelectorAll('.exam-item').forEach((item, idx) => {
    item.classList.toggle('active', idx === index);
  });

  showReviewInterface(exam);
}

// Show review interface
function showReviewInterface(exam) {
  const resultsContainer = document.getElementById('correction-results');
  const reviewInterface = document.getElementById('review-interface');

  if (resultsContainer) resultsContainer.style.display = 'none';
  if (reviewInterface) {
    reviewInterface.classList.add('active');
    reviewInterface.style.display = 'flex';
  }

  // Populate review data
  const reviewImage = document.getElementById('review-image');
  if (reviewImage && exam.image_url) {
    reviewImage.src = exam.image_url;
  }

  const ocrText = document.getElementById('ocr-text');
  if (ocrText) {
    ocrText.textContent = exam.ocr_text || 'OCR-Text wird geladen...';
  }

  // Render answers
  const answersContainer = document.getElementById('answers-container');
  if (answersContainer && exam.answers) {
    answersContainer.innerHTML = exam.answers.map((ans, idx) => `
      <div class="answer-section">
        <div class="answer-header">
          <span class="answer-task">${ans.task}</span>
          <div class="answer-points">
            <input type="number" id="answer-points-${idx}" value="${ans.points}" min="0" max="${ans.max}">
            <span>/ ${ans.max}</span>
          </div>
        </div>
        <div class="answer-text">${ans.text || 'Keine Antwort erkannt'}</div>
        <div class="ai-feedback">${ans.feedback || 'AI-Feedback wird generiert...'}</div>
      </div>
    `).join('');
  }

  // Update total
  updateTotalPoints(exam);
}

// Update total points display
function updateTotalPoints(exam) {
  const totalEl = document.getElementById('total-points');
  if (totalEl) {
    totalEl.textContent = `${exam.points} / ${exam.max_points}`;
  }

  const gradeSelect = document.getElementById('grade-select');
  if (gradeSelect) {
    gradeSelect.value = exam.grade;
  }
}

// Navigate exams
function previousExam() {
  if (currentExamIndex > 0) {
    selectExam(currentExamIndex - 1);
  }
}

async function saveAndNextExam() {
  // Save current exam data
  const exam = correctedExams[currentExamIndex];
  if (exam && exam.answers) {
    exam.answers.forEach((ans, idx) => {
      const input = document.getElementById(`answer-points-${idx}`);
      if (input) {
        ans.points = parseInt(input.value) || 0;
      }
    });
    exam.points = exam.answers.reduce((sum, a) => sum + a.points, 0);
    exam.percentage = (exam.points / exam.max_points * 100) || 0;
    exam.grade = document.getElementById('grade-select')?.value || exam.grade;

    // Save to API if we have a correction ID
    if (exam.id) {
      try {
        const evaluations = exam.answers.map((ans, idx) => ({
          question_number: idx + 1,
          extracted_text: ans.text || '',
          points_possible: ans.max,
          points_awarded: ans.points,
          feedback: ans.feedback || '',
          is_correct: ans.points >= ans.max * 0.5,
          confidence: 0.8
        }));

        await fetch(`/api/corrections/${exam.id}`, {
          method: 'PUT',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            evaluations: evaluations,
            total_points: exam.points,
            grade: exam.grade,
            status: 'reviewing'
          })
        });

        console.log(`Korrektur ${exam.id} gespeichert`);
      } catch (e) {
        console.error('Speichern fehlgeschlagen:', e);
      }
    }
  }

  // Move to next
  if (currentExamIndex < correctedExams.length - 1) {
    selectExam(currentExamIndex + 1);
  } else {
    // All done - mark as completed if we have IDs
    for (const exam of correctedExams) {
      if (exam.id) {
        try {
          await fetch(`/api/corrections/${exam.id}/complete`, { method: 'POST' });
        } catch (e) {
          console.error(`Complete failed for ${exam.id}:`, e);
        }
      }
    }

    // Show summary
    hideReviewInterface();
    showCorrectionResults(correctedExams);

    // Update stats
    const avg = correctedExams.length
      ? (correctedExams.reduce((sum, e) => sum + (e.percentage || 0), 0) / correctedExams.length).toFixed(1)
      : '-';
    document.getElementById('stat-average').textContent = avg + '%';
  }
}

function hideReviewInterface() {
  const resultsContainer = document.getElementById('correction-results');
  const reviewInterface = document.getElementById('review-interface');

  if (reviewInterface) {
    reviewInterface.classList.remove('active');
    reviewInterface.style.display = 'none';
  }
  if (resultsContainer) {
    resultsContainer.style.display = 'block';
  }
}

// Export correction results - uses /api/corrections API
async function exportCorrectionResults(format) {
  console.log(`Exportiere Ergebnisse als ${format}...`);

  if (!correctedExams.length) {
    alert('Keine Ergebnisse zum Exportieren vorhanden.');
    return;
  }

  if (format === 'csv') {
    // CSV export - client-side
    const csv = [
      'Name,Punkte,MaxPunkte,Prozent,Note',
      ...correctedExams.map(e =>
        `"${e.student_name || e.filename}",${e.points},${e.max_points},${e.percentage?.toFixed(1) || 0},${e.grade}`
      )
    ].join('\\n');

    const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'klausur-ergebnisse.csv';
    a.click();
    URL.revokeObjectURL(url);

  } else if (format === 'pdf') {
    // PDF export - via API for each correction
    try {
      for (const exam of correctedExams) {
        if (!exam.id) continue;

        const resp = await fetch(`/api/corrections/${exam.id}/export-pdf`);
        if (!resp.ok) {
          console.error(`PDF export failed for ${exam.student_name}`);
          continue;
        }

        const blob = await resp.blob();
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `korrektur_${exam.student_name || 'unbekannt'}.pdf`;
        a.click();
        URL.revokeObjectURL(url);

        // Small delay between downloads
        await new Promise(resolve => setTimeout(resolve, 300));
      }
      alert(`${correctedExams.length} PDF(s) wurden heruntergeladen.`);
    } catch (e) {
      console.error('PDF export error:', e);
      alert('PDF-Export fehlgeschlagen: ' + e.message);
    }

  } else if (format === 'excel') {
    // Excel export - generate XLSX-like structure
    const headers = ['Name', 'Punkte', 'MaxPunkte', 'Prozent', 'Note'];
    const rows = correctedExams.map(e => [
      e.student_name || e.filename,
      e.points,
      e.max_points,
      e.percentage?.toFixed(1) || 0,
      e.grade
    ]);

    // Create TSV (Tab-separated) which Excel can open
    const tsv = [
      headers.join('\\t'),
      ...rows.map(row => row.join('\\t'))
    ].join('\\n');

    const blob = new Blob([tsv], { type: 'application/vnd.ms-excel;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'klausur-ergebnisse.xls';
    a.click();
    URL.revokeObjectURL(url);
  }
}

// Show Correction Panel
function showCorrectionPanel() {
  console.log('showCorrectionPanel called');
  hideAllPanels();
  hideStudioSubMenu();
  const panel = document.getElementById('panel-correction');
  if (panel) {
    panel.style.display = 'flex';
    loadCorrectionModule();
    console.log('Correction panel shown');
  } else {
    console.error('panel-correction not found');
  }
}
"""
