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 (e.g., 'galerie-metadata.json'), 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 GALERIE_DIR = getDataPath('galerie')
const GALERIE_METADATA = getDataPath('galerie-metadata.json')

// Multer-Konfiguration für Bild-Uploads
// Temporärer Dateiname, wird später basierend auf Titel umbenannt
const storage = multer.diskStorage({
  destination: async (req, file, cb) => {
    try {
      await fs.mkdir(GALERIE_DIR, { recursive: true })
      await fs.mkdir(path.join(GALERIE_DIR, 'originals'), { recursive: true })
      await fs.mkdir(path.join(GALERIE_DIR, 'previews'), { recursive: true })
      cb(null, path.join(GALERIE_DIR, 'originals'))
    } catch (error) {
      cb(error)
    }
  },
  filename: (req, file, cb) => {
    // Temporärer Dateiname, wird später umbenannt
    const ext = path.extname(file.originalname)
    const tempFilename = `temp_${randomUUID()}${ext}`
    cb(null, tempFilename)
  }
})

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
  }
})

async function readGalerieMetadata() {
  try {
    const data = await fs.readFile(GALERIE_METADATA, 'utf-8')
    return JSON.parse(data)
  } catch (error) {
    if (error.code === 'ENOENT') {
      return []
    }
    throw error
  }
}

async function writeGalerieMetadata(metadata) {
  await fs.writeFile(GALERIE_METADATA, JSON.stringify(metadata, null, 2), 'utf-8')
}

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
    const body = event.node.req.body || {}
    const isPublic = body.isPublic === 'true' || body.isPublic === true

    if (!file) {
      throw createError({
        statusCode: 400,
        statusMessage: 'Keine Bilddatei hochgeladen'
      })
    }

    // Titel ist Pflichtfeld
    if (!body.title || !body.title.trim()) {
      // Lösche die hochgeladene Datei
      await fs.unlink(file.path).catch(() => {
        // Datei bereits gelöscht oder nicht vorhanden, ignorieren
      })
      throw createError({
        statusCode: 400,
        statusMessage: 'Titel ist ein Pflichtfeld'
      })
    }

    // Generiere Dateinamen basierend auf Titel
    const titleSlug = body.title.trim()
      .toLowerCase()
      .replace(/[^a-z0-9]+/g, '-')
      .replace(/^-+|-+$/g, '')
      .substring(0, 100) // Max 100 Zeichen
    
    // 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 filename = `${titleSlug}_${randomUUID().substring(0, 8)}${ext}`
    const previewFilename = `preview_${filename}`

    // Originalbild verarbeiten: re-encode (EXIF entfernen) + Pixel/DIM-Limit
    // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
    const originalPath = path.join(GALERIE_DIR, 'originals', filename)

    const maxPixels = Number(process.env.IMAGE_MAX_PIXELS || 20_000_000) // 20MP
    const maxDim = Number(process.env.IMAGE_MAX_DIM || 4000) // px

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

    let pipeline = sharp(file.path).rotate()

    if (w > 0 && h > 0) {
      const pixels = w * h
      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 {
      pipeline = pipeline.resize(maxDim, maxDim, { fit: 'inside', withoutEnlargement: true })
    }

    await pipeline.toFile(originalPath)
    // Temp-Datei löschen
    await fs.unlink(file.path).catch(() => {})
    
    // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
    const previewPath = path.join(GALERIE_DIR, 'previews', previewFilename)

    // Thumbnail erstellen (150x150px) mit automatischer EXIF-Orientierungskorrektur
    await sharp(originalPath)
      .rotate() // Korrigiert automatisch EXIF-Orientierung
      .resize(150, 150, {
        fit: 'inside',
        withoutEnlargement: true
      })
      .toFile(previewPath)

    // Metadaten speichern
    const metadata = await readGalerieMetadata()
    const newImage = {
      id: randomUUID(),
      filename,
      previewFilename,
      title: body.title.trim(),
      description: body.description || '',
      isPublic,
      uploadedBy: user.id,
      uploadedAt: new Date().toISOString(),
      originalName: file.originalname
    }

    metadata.push(newImage)
    await writeGalerieMetadata(metadata)

    return {
      success: true,
      message: 'Bild erfolgreich hochgeladen',
      image: {
        id: newImage.id,
        title: newImage.title,
        isPublic: newImage.isPublic
      }
    }

  } catch (error) {
    console.error('Fehler beim Bild-Upload:', error)
    
    if (error.statusCode) {
      throw error
    }
    
    if (error.code === 'LIMIT_FILE_SIZE') {
      throw createError({
        statusCode: 413,
        statusMessage: 'Datei zu groß (max. 10MB)'
      })
    }
    
    if (error.message && error.message.includes('Nur Bilddateien')) {
      throw createError({
        statusCode: 400,
        statusMessage: error.message
      })
    }
    
    throw createError({
      statusCode: 500,
      statusMessage: 'Fehler beim Hochladen des Bildes'
    })
  }
})

