const fs = require('fs/promises')
const path = require('path')
const sharp = require('sharp')
const {
  ensureData,
  closePool,
  listReferencedUploadUsage,
  replaceUploadSourceReferences,
} = require('../src/db')
const { writeOptimizedImage } = require('../src/lib/image-storage')

const BACKEND_ROOT = path.join(__dirname, '..')

function inferMimeType(src, metadata) {
  const format = String(metadata?.format || '').toLowerCase()
  if (format === 'jpeg' || format === 'jpg') return 'image/jpeg'
  if (format === 'png') return 'image/png'
  if (format === 'gif') return 'image/gif'
  if (format === 'webp') return 'image/webp'
  if (format === 'svg' || format === 'svg+xml') return 'image/svg+xml'
  if (format === 'avif') return 'image/avif'

  const ext = path.extname(src || '').toLowerCase()
  if (ext === '.jpg' || ext === '.jpeg') return 'image/jpeg'
  if (ext === '.png') return 'image/png'
  if (ext === '.gif') return 'image/gif'
  if (ext === '.webp') return 'image/webp'
  if (ext === '.svg') return 'image/svg+xml'
  if (ext === '.avif') return 'image/avif'
  return 'application/octet-stream'
}

function getOptimizationConfig(roles) {
  const roleSet = new Set(roles || [])
  if (roleSet.has('avatar')) {
    return { directory: 'avatars', width: 512, height: 512, fit: 'cover', quality: 82 }
  }
  if (roleSet.has('topic-thumbnail') || roleSet.has('tierlist-thumbnail') || roleSet.has('template-thumbnail')) {
    return { directory: 'legacy-thumbnails', width: 1280, height: 1280, fit: 'inside', quality: 84 }
  }
  return { directory: 'legacy-items', width: 512, height: 512, fit: 'inside', quality: 84 }
}

async function createFileLike(src) {
  const absolutePath = path.join(BACKEND_ROOT, src.replace(/^\//, ''))
  const [buffer, stat] = await Promise.all([fs.readFile(absolutePath), fs.stat(absolutePath)])
  let metadata = {}
  try {
    metadata = await sharp(buffer, { failOn: 'none' }).metadata()
  } catch (error) {
    metadata = {}
  }
  return {
    file: {
      originalname: path.basename(src),
      mimetype: inferMimeType(src, metadata),
      size: Number(stat.size || 0),
      buffer,
    },
    absolutePath,
  }
}

async function main() {
  await ensureData()
  const usageEntries = await listReferencedUploadUsage()
  const legacyEntries = usageEntries.filter((entry) => entry.src && entry.src.startsWith('/uploads/') && !entry.src.startsWith('/uploads/assets/'))

  const summary = {
    scanned: legacyEntries.length,
    migrated: 0,
    reusedAsset: 0,
    unchanged: 0,
    missingFiles: 0,
    failed: 0,
    updatedRows: 0,
  }

  for (const entry of legacyEntries) {
    const config = getOptimizationConfig(entry.roles)
    try {
      const { file } = await createFileLike(entry.src)
      const optimized = await writeOptimizedImage({ file, ...config })
      if (optimized.src === entry.src) {
        summary.unchanged += 1
        continue
      }
      const replaced = await replaceUploadSourceReferences({ fromSrc: entry.src, toSrc: optimized.src })
      summary.updatedRows += Number(replaced.updatedRows || 0)
      if (optimized.reused) summary.reusedAsset += 1
      else summary.migrated += 1
    } catch (error) {
      if (error?.code === 'ENOENT') {
        summary.missingFiles += 1
        continue
      }
      summary.failed += 1
      console.error('[migrate-legacy-uploads-to-assets] failed:', entry.src, error?.message || error)
    }
  }

  console.log(JSON.stringify(summary, null, 2))
}

main()
  .catch((error) => {
    console.error(error)
    process.exitCode = 1
  })
  .finally(async () => {
    await closePool()
  })
