import multer from 'multer'
import fs from 'fs/promises'
import path from 'path'
import sharp from 'sharp'
import { getUserFromToken, verifyToken, hasAnyRole } from '../../utils/auth.js'
import { randomUUID } from 'crypto'
import { clamp } from '../../utils/upload-validation.js'

// 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 ('personen'), never user input
const getDataPath = (filename) => {
  const cwd = process.cwd()
  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)
  }
  // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
  return path.join(cwd, 'server/data', filename)
}

const PERSONEN_DIR = getDataPath('personen')

// Multer-Konfiguration für Bild-Uploads
const storage = multer.diskStorage({
  destination: async (req, file, cb) => {
    try {
      await fs.mkdir(PERSONEN_DIR, { recursive: true })
      cb(null, PERSONEN_DIR)
    } catch (error) {
      cb(error)
    }
  },
  filename: (req, file, cb) => {
    const ext = path.extname(file.originalname)
    const filename = `${randomUUID()}${ext}`
    cb(null, filename)
  }
})

const upload = multer({
  storage,
  fileFilter: (req, file, cb) => {
    const allowedMimes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp']
    if (allowedMimes.includes(file.mimetype)) {
      cb(null, true)
    } else {
      cb(new Error('Nur Bilddateien sind erlaubt (JPEG, PNG, GIF, WebP)'), false)
    }
  },
  limits: {
    fileSize: 10 * 1024 * 1024 // 10MB Limit
  }
})

export default defineEventHandler(async (event) => {
  try {
    // Authentifizierung prüfen
    const token = getCookie(event, 'auth_token') || getHeader(event, 'authorization')?.replace('Bearer ', '')
    
    if (!token) {
      throw createError({
        statusCode: 401,
        statusMessage: 'Nicht authentifiziert'
      })
    }

    const decoded = verifyToken(token)
    if (!decoded) {
      throw createError({
        statusCode: 401,
        statusMessage: 'Ungültiges Token'
      })
    }

    const user = await getUserFromToken(token)
    if (!user || !hasAnyRole(user, 'admin', 'vorstand')) {
      throw createError({
        statusCode: 403,
        statusMessage: 'Keine Berechtigung zum Hochladen von Bildern'
      })
    }

    // Multer-Middleware für multipart/form-data
    await new Promise((resolve, reject) => {
      upload.single('image')(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 Bilddatei hochgeladen'
      })
    }

    // Bild mit sharp verarbeiten (EXIF-Orientierung korrigieren und optional resize)
    const originalPath = file.path
    
    // Validiere Dateiendung
    const ext = path.extname(file.originalname).toLowerCase()
    const allowedExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp']
    if (!allowedExtensions.includes(ext)) {
      await fs.unlink(file.path).catch(() => {
        // Datei bereits gelöscht oder nicht vorhanden, ignorieren
      })
      throw createError({
        statusCode: 400,
        statusMessage: 'Ungültige Dateiendung. Nur Bilddateien sind erlaubt.'
      })
    }
    
    const newFilename = `${randomUUID()}${ext}`
    // Zusätzliche Sicherheit: Validiere generierten Dateinamen
    const sanitizedFilename = path.basename(path.normalize(newFilename))
    if (sanitizedFilename !== newFilename) {
      throw createError({
        statusCode: 500,
        statusMessage: 'Fehler beim Generieren des Dateinamens'
      })
    }
    // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
    const newPath = path.join(PERSONEN_DIR, sanitizedFilename)

    // Bild verarbeiten: EXIF-Orientierung korrigieren
    const maxPixels = Number(process.env.IMAGE_MAX_PIXELS || 20_000_000) // 20MP
    const maxDim = Number(process.env.IMAGE_MAX_DIM || 2500) // px

    const meta = await sharp(originalPath).metadata()
    const w = meta.width || 0
    const h = meta.height || 0

    let pipeline = sharp(originalPath).rotate()

    if (w > 0 && h > 0) {
      const pixels = w * h
      // Falls extrem groß: auf maxPixels runter skalieren
      if (pixels > maxPixels) {
        const scale = Math.sqrt(maxPixels / pixels)
        const nw = clamp(Math.floor(w * scale), 1, maxDim)
        const nh = clamp(Math.floor(h * scale), 1, maxDim)
        pipeline = pipeline.resize(nw, nh, { fit: 'inside', withoutEnlargement: true })
      } else if (w > maxDim || h > maxDim) {
        pipeline = pipeline.resize(maxDim, maxDim, { fit: 'inside', withoutEnlargement: true })
      }
    } else {
      // Unbekannte Dimensionen: dennoch hartes Größenlimit
      pipeline = pipeline.resize(maxDim, maxDim, { fit: 'inside', withoutEnlargement: true })
    }

    // toFile re-encodiert => EXIF/Metadata wird entfernt (sofern nicht withMetadata() genutzt wird)
    await pipeline.toFile(newPath)

    // Temporäre Datei löschen
    await fs.unlink(originalPath).catch(() => {
      // Datei bereits gelöscht oder nicht vorhanden, ignorieren
    })

    return {
      success: true,
      message: 'Bild erfolgreich hochgeladen',
      filename: newFilename
    }
  } catch (error) {
    console.error('Fehler beim Hochladen des Personenfotos:', error)
    
    if (error.statusCode) {
      throw error
    }
    
    throw createError({
      statusCode: 500,
      statusMessage: error.message || 'Fehler beim Hochladen des Bildes'
    })
  }
})

