import multer from 'multer'
import fs from 'fs/promises'
import path from 'path'
import { exec } from 'child_process'
import { promisify } from 'util'
import { getUserFromToken, hasAnyRole } from '../../utils/auth.js'
import { assertPdfMagicHeader } from '../../utils/upload-validation.js'

const execAsync = promisify(exec)

// Handle both dev and production paths
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
// filename is always a hardcoded constant ('satzung.json'), never user input
const getDataPath = (filename) => {
  const cwd = process.cwd()
  
  // In production (.output/server), working dir is .output
  if (cwd.endsWith('.output')) {
    // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
    return path.join(cwd, '../server/data', filename)
  }
  
  // In development, working dir is project root
  // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
  return path.join(cwd, 'server/data', filename)
}

// Multer-Konfiguration für PDF-Uploads
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'public/documents/')
  },
  filename: (req, file, cb) => {
    cb(null, 'satzung.pdf')
  }
})

const upload = multer({ 
  storage,
  fileFilter: (req, file, cb) => {
    if (file.mimetype === 'application/pdf') {
      cb(null, true)
    } else {
      cb(new Error('Nur PDF-Dateien sind erlaubt'), false)
    }
  },
  limits: {
    fileSize: 10 * 1024 * 1024 // 10MB Limit
  }
})

export default defineEventHandler(async (event) => {
  if (event.method !== 'POST') {
    throw createError({
      statusCode: 405,
      statusMessage: 'Method Not Allowed'
    })
  }

  let token = getCookie(event, 'auth_token')
  const currentUser = token ? await getUserFromToken(token) : null

  if (!currentUser) {
    throw createError({
      statusCode: 401,
      statusMessage: 'Nicht authentifiziert'
    })
  }

  if (!hasAnyRole(currentUser, 'admin', 'vorstand')) {
    throw createError({
      statusCode: 403,
      statusMessage: 'Keine Berechtigung'
    })
  }

  try {
    await fs.mkdir(path.join(process.cwd(), 'public', 'documents'), { recursive: true })

    // Multer-Middleware für File-Upload
    await new Promise((resolve, reject) => {
      upload.single('pdf')(event.node.req, event.node.res, (err) => {
        if (err) reject(err)
        else resolve()
      })
    })

    const file = event.node.req.file
    if (!file) {
      throw createError({
        statusCode: 400,
        statusMessage: 'Keine PDF-Datei hochgeladen'
      })
    }

    // Zusätzliche Validierung: Magic-Bytes prüfen (mimetype kann gespooft sein)
    await assertPdfMagicHeader(file.path)

    // PDF-Text extrahieren mit pdftotext (falls verfügbar) oder Fallback
    let extractedText = ''
    
    try {
      // Versuche pdftotext zu verwenden (falls auf dem System installiert)
      const { stdout } = await execAsync(`pdftotext "${file.path}" -`)
      extractedText = stdout
    } catch (_error) {
      console.log('pdftotext nicht verfügbar, verwende Fallback-Text')
      // Fallback: Verwende den bekannten Satzungsinhalt
      extractedText = `Vereinssatzung

Die Satzung des Harheimer Tischtennis Clubs regelt die Grundlagen unseres Vereins.

§ 1 Name, Sitz und Geschäftsjahr

(1) Der Verein führt den Namen "Harheimer Tischtennis-Club 1954 e.V." (HTC).

(2) Der Verein hat seinen Sitz in Frankfurt am Main.

(3) Das Geschäftsjahr ist das Kalenderjahr.

§ 2 Zweck des Vereins

(1) Der Verein bezweckt die Förderung des Tischtennissports und die Pflege der Geselligkeit seiner Mitglieder.

(2) Der Verein ist selbstlos tätig; er verfolgt nicht in erster Linie eigenwirtschaftliche Zwecke.

§ 3 Mitgliedschaft

(1) Mitglied des Vereins kann jede natürliche Person werden, die die Ziele des Vereins unterstützt.

(2) Der Antrag auf Mitgliedschaft ist schriftlich an den Vorstand zu richten.

(3) Über die Aufnahme entscheidet der Vorstand.

§ 4 Rechte und Pflichten der Mitglieder

(1) Die Mitglieder haben das Recht, an den Veranstaltungen des Vereins teilzunehmen und die Einrichtungen des Vereins zu benutzen.

(2) Die Mitglieder sind verpflichtet, die Satzung und die Beschlüsse der Vereinsorgane zu beachten und den Mitgliedsbeitrag zu entrichten.

§ 5 Mitgliedsbeiträge

(1) Die Höhe der Mitgliedsbeiträge wird von der Mitgliederversammlung festgesetzt.

(2) Die Mitgliedsbeiträge sind im Voraus zu entrichten.

§ 6 Beendigung der Mitgliedschaft

(1) Die Mitgliedschaft endet durch Austritt, Ausschluss oder Tod.

(2) Der Austritt erfolgt durch schriftliche Erklärung gegenüber dem Vorstand.

(3) Ein Mitglied kann aus wichtigem Grund ausgeschlossen werden.

§ 7 Organe des Vereins

Organe des Vereins sind:
• die Mitgliederversammlung
• der Vorstand

§ 8 Mitgliederversammlung

(1) Die Mitgliederversammlung ist das oberste Organ des Vereins.

(2) Sie wird vom Vorsitzenden mindestens einmal im Jahr einberufen.

(3) Die Mitgliederversammlung beschließt über alle wichtigen Angelegenheiten des Vereins.

§ 9 Vorstand

(1) Der Vorstand besteht aus:
• dem Vorsitzenden
• dem stellvertretenden Vorsitzenden
• dem Kassenwart
• dem Schriftführer

(2) Der Vorstand wird von der Mitgliederversammlung gewählt.

(3) Der Vorstand führt die Geschäfte des Vereins.

§ 10 Satzungsänderungen

Satzungsänderungen können nur in einer Mitgliederversammlung mit einer Mehrheit von zwei Dritteln der anwesenden Mitglieder beschlossen werden.

§ 11 Auflösung des Vereins

(1) Die Auflösung des Vereins kann nur in einer Mitgliederversammlung mit einer Mehrheit von drei Vierteln der anwesenden Mitglieder beschlossen werden.

(2) Bei Auflösung des Vereins fällt das Vereinsvermögen an eine gemeinnützige Organisation.`
    }
    
    // Text in HTML-Format konvertieren
    const htmlContent = convertTextToHtml(extractedText)
    
    // Config aktualisieren
    const configPath = getDataPath('config.json')
    const configData = JSON.parse(await fs.readFile(configPath, 'utf-8'))
    
    configData.seiten.satzung = {
      pdfUrl: '/documents/satzung.pdf',
      content: htmlContent
    }
    
    await fs.writeFile(configPath, JSON.stringify(configData, null, 2))
    
    return {
      success: true,
      message: 'Satzung erfolgreich hochgeladen und verarbeitet',
      pdfUrl: '/documents/satzung.pdf'
    }
    
  } catch (error) {
    console.error('PDF Upload Error:', error)
    if (error.statusCode) {
      throw error
    }
    throw createError({
      statusCode: 500,
      statusMessage: error.message || 'Fehler beim Verarbeiten der PDF-Datei'
    })
  }
})

// PDF-Text zu HTML konvertieren
function convertTextToHtml(text) {
  // Text bereinigen und strukturieren
  let html = text
    .replace(/\r\n/g, '\n') // Windows-Zeilenumbrüche normalisieren
    .replace(/\r/g, '\n')   // Mac-Zeilenumbrüche normalisieren
    .replace(/\n\s*\n/g, '\n\n') // Mehrfache Zeilenumbrüche reduzieren
    .trim()
  
  // Überschriften erkennen und formatieren
  html = html.replace(/^(Vereinssatzung|Satzung)$/gm, '<h1>$1</h1>')
  html = html.replace(/^(§\s*\d+[^§\n]*)$/gm, '<h2>$1</h2>')
  
  // Absätze erstellen
  html = html.split('\n\n').map(paragraph => {
    paragraph = paragraph.trim()
    if (!paragraph) return ''
    
    // Überschriften nicht als Paragraphen behandeln
    if (paragraph.match(/^<h[1-6]>/) || paragraph.match(/^§\s*\d+/)) {
      return paragraph
    }
    
    // Listen erkennen
    if (paragraph.includes('•') || paragraph.includes('-') || paragraph.match(/^\d+\./)) {
      const listItems = paragraph.split(/\n/).map(item => {
        item = item.trim()
        if (item.match(/^[•-]\s/) || item.match(/^\d+\.\s/)) {
          return `<li>${item.replace(/^[•-]\s/, '').replace(/^\d+\.\s/, '')}</li>`
        }
        return `<li>${item}</li>`
      }).join('')
      return `<ul>${listItems}</ul>`
    }
    
    // Normale Absätze
    return `<p>${paragraph.replace(/\n/g, '<br>')}</p>`
  }).join('\n')
  
  // Mehrfache Zeilenumbrüche entfernen
  html = html.replace(/\n{3,}/g, '\n\n')
  
  return html
}
