/**
 * Shared utilities for the upload system.
 * These are pure functions – no React, no side effects.
 */

// ─── Constants ────────────────────────────────────────────────────────────────
export const IMAGE_EXTENSIONS = new Set(['jpg', 'jpeg', 'png', 'webp'])
export const IMAGE_MIME = new Set(['image/jpeg', 'image/png', 'image/webp'])
export const ARCHIVE_EXTENSIONS = new Set(['zip', 'rar', '7z', 'tar', 'gz'])
export const ARCHIVE_MIME = new Set([
  'application/zip',
  'application/x-zip-compressed',
  'application/x-rar-compressed',
  'application/vnd.rar',
  'application/x-7z-compressed',
  'application/x-tar',
  'application/gzip',
  'application/x-gzip',
  'application/octet-stream',
])

export const PRIMARY_IMAGE_MAX_BYTES = 50 * 1024 * 1024    // 50 MB
export const PRIMARY_ARCHIVE_MAX_BYTES = 200 * 1024 * 1024 // 200 MB
export const SCREENSHOT_MAX_BYTES = 10 * 1024 * 1024       // 10 MB

// ─── Type detection ───────────────────────────────────────────────────────────
export function getExtension(fileName = '') {
  const parts = String(fileName).toLowerCase().split('.')
  return parts.length > 1 ? parts.pop() : ''
}

/**
 * @param {File} file
 * @returns {'image' | 'archive' | 'unsupported'}
 */
export function detectFileType(file) {
  if (!file) return 'unknown'
  const extension = getExtension(file.name)
  const mime = String(file.type || '').toLowerCase()
  if (IMAGE_MIME.has(mime) || IMAGE_EXTENSIONS.has(extension)) return 'image'
  if (ARCHIVE_MIME.has(mime) || ARCHIVE_EXTENSIONS.has(extension)) return 'archive'
  return 'unsupported'
}

// ─── Formatting ───────────────────────────────────────────────────────────────
export function formatBytes(bytes) {
  if (!Number.isFinite(bytes) || bytes <= 0) return '—'
  if (bytes < 1024) return `${bytes} B`
  const kb = bytes / 1024
  if (kb < 1024) return `${kb.toFixed(1)} KB`
  const mb = kb / 1024
  if (mb < 1024) return `${mb.toFixed(1)} MB`
  return `${(mb / 1024).toFixed(2)} GB`
}

// ─── Image utils ──────────────────────────────────────────────────────────────
/**
 * @param {File} file
 * @returns {Promise<{width: number, height: number}>}
 */
export function readImageDimensions(file) {
  return new Promise((resolve, reject) => {
    const blobUrl = URL.createObjectURL(file)
    const img = new Image()
    img.onload = () => {
      resolve({ width: img.naturalWidth, height: img.naturalHeight })
      URL.revokeObjectURL(blobUrl)
    }
    img.onerror = () => {
      reject(new Error('image_read_failed'))
      URL.revokeObjectURL(blobUrl)
    }
    img.src = blobUrl
  })
}

// ─── Category tree ────────────────────────────────────────────────────────────
export function buildCategoryTree(contentTypes = []) {
  const rootsById = new Map()
  contentTypes.forEach((type) => {
    const categories = Array.isArray(type?.categories) ? type.categories : []
    categories.forEach((category) => {
      if (!category?.id) return
      const key = String(category.id)
      if (!rootsById.has(key)) {
        rootsById.set(key, {
          id: key,
          name: category.name || `Category ${category.id}`,
          children: [],
        })
      }
      const root = rootsById.get(key)
      const children = Array.isArray(category?.children) ? category.children : []
      children.forEach((child) => {
        if (!child?.id) return
        const exists = root.children.some((item) => String(item.id) === String(child.id))
        if (!exists) {
          root.children.push({ id: String(child.id), name: child.name || `Subcategory ${child.id}` })
        }
      })
    })
  })
  return Array.from(rootsById.values())
}

// ─── Content type helpers ─────────────────────────────────────────────────────
export function getContentTypeValue(type) {
  if (!type) return ''
  return String(type.id ?? type.key ?? type.slug ?? type.name ?? '')
}

export function getContentTypeVisualKey(type) {
  const raw = String(type?.slug || type?.name || type?.key || '').toLowerCase()
  const normalized = raw.replace(/\s+/g, '_').replace(/[^a-z0-9_]/g, '')
  if (normalized.includes('wallpaper')) return 'wallpapers'
  if (normalized.includes('skin')) return 'skins'
  if (normalized.includes('photo')) return 'photography'
  return 'other'
}

// ─── Processing status helpers ────────────────────────────────────────────────
export function getProcessingTransparencyLabel(processingStatus, machineState) {
  if (!['processing', 'finishing', 'publishing'].includes(machineState)) return ''
  const normalized = String(processingStatus || '').toLowerCase()
  if (normalized === 'generating_preview') return 'Generating preview'
  if (['processed', 'ready', 'published', 'queued', 'publish_ready'].includes(normalized)) {
    return 'Preparing for publish'
  }
  return 'Analyzing content'
}
