import crypto from 'node:crypto'
import fs from 'node:fs'
import path from 'node:path'

export function safeImageExt(filename) {
  const ext = path.extname(String(filename || '')).toLowerCase()
  const allowed = new Set(['.png', '.jpg', '.jpeg', '.webp'])
  return allowed.has(ext) ? ext : null
}

export function uploadError(message, statusCode = 400) {
  const err = new Error(message)
  err.statusCode = statusCode
  return err
}

export async function persistMultipartImages(request, { maxFiles = 10, maxFileBytes, subdir = '', eager = false }) {
  if (!request.isMultipart()) {
    throw uploadError('Ожидается multipart/form-data')
  }

  const uploadsDir = path.join(process.cwd(), 'uploads')
  const targetDir = subdir ? path.join(uploadsDir, subdir) : uploadsDir
  await fs.promises.mkdir(targetDir, { recursive: true })

  const urls = []
  const parts = request.parts({
    limits: {
      fileSize: maxFileBytes,
      files: maxFiles,
    },
  })
  for await (const part of parts) {
    if (!part.file) continue
    if (urls.length >= maxFiles) {
      throw uploadError(`Можно загрузить не более ${maxFiles} файл(ов)`)
    }
    const ext = safeImageExt(part.filename)
    if (!ext) {
      throw uploadError('Разрешены только файлы: png, jpg, jpeg, webp')
    }

    const uuid = crypto.randomUUID()
    const fileName = `${uuid}${ext}`
    const fullPath = path.join(targetDir, fileName)
    await fs.promises.writeFile(fullPath, await part.toBuffer())

    let finalUrl = subdir ? `/uploads/${subdir}/${fileName}` : `/uploads/${fileName}`

    if (eager) {
      try {
        const { generateAllSizes, convertOriginalToWebp } = await import('./image-resize.js')
        await generateAllSizes(uuid, subdir, fullPath)
        finalUrl = await convertOriginalToWebp(uuid, subdir)
      } catch (error) {
        await fs.promises.unlink(fullPath).catch(() => {})
        throw error
      }
    }

    urls.push(finalUrl)
  }

  if (urls.length === 0) {
    throw uploadError(
      'Файлы не получены. Проверьте, что запрос multipart/form-data и поля — файлы изображений (png, jpg, webp).',
    )
  }

  return urls
}

/** Сохранить один буфер изображения в uploads/, вернуть путь `/uploads/...`. */
export async function saveImageBufferToUploads(originalFilename, buffer, subdir = '') {
  const ext = safeImageExt(originalFilename)
  if (!ext) {
    throw uploadError('Разрешены только файлы: png, jpg, jpeg, webp')
  }

  const uploadsDir = path.join(process.cwd(), 'uploads')
  const targetDir = subdir ? path.join(uploadsDir, subdir) : uploadsDir
  await fs.promises.mkdir(targetDir, { recursive: true })

  const fileName = `${crypto.randomUUID()}${ext}`
  const fullPath = path.join(targetDir, fileName)
  await fs.promises.writeFile(fullPath, buffer)
  return subdir ? `/uploads/${subdir}/${fileName}` : `/uploads/${fileName}`
}
