import { useEffect, useRef, useState } from 'react'
import {
  detectFileType,
  formatBytes,
  readImageDimensions,
  getExtension,
  IMAGE_MIME,
  IMAGE_EXTENSIONS,
  PRIMARY_IMAGE_MAX_BYTES,
  PRIMARY_ARCHIVE_MAX_BYTES,
  SCREENSHOT_MAX_BYTES,
} from '../../lib/uploadUtils'

// ─── Primary file validation ──────────────────────────────────────────────────
async function validatePrimaryFile(file) {
  const errors = []
  const warnings = []
  const type = detectFileType(file)

  if (!file) {
    return {
      type: 'unknown',
      errors: [],
      warnings,
      metadata: { resolution: '—', size: '—', type: '—' },
      previewUrl: '',
    }
  }

  const metadata = {
    resolution: '—',
    size: formatBytes(file.size),
    type: file.type || getExtension(file.name) || 'unknown',
  }

  if (type === 'unsupported') {
    errors.push('Unsupported file type. Use image (jpg/jpeg/png/webp) or archive (zip/rar/7z/tar/gz).')
  }

  if (type === 'image') {
    if (file.size > PRIMARY_IMAGE_MAX_BYTES) {
      errors.push('Image exceeds 50MB maximum size.')
    }
    try {
      const dimensions = await readImageDimensions(file)
      metadata.resolution = `${dimensions.width} × ${dimensions.height}`
      if (dimensions.width < 800 || dimensions.height < 600) {
        errors.push('Image resolution must be at least 800×600.')
      }
    } catch {
      errors.push('Unable to read image resolution.')
    }
  }

  if (type === 'archive') {
    metadata.resolution = 'n/a'
    if (file.size > PRIMARY_ARCHIVE_MAX_BYTES) {
      errors.push('Archive exceeds 200MB maximum size.')
    }
    warnings.push('Archive upload requires at least one valid screenshot.')
  }

  const previewUrl = type === 'image' ? URL.createObjectURL(file) : ''

  return { type, errors, warnings, metadata, previewUrl }
}

// ─── Screenshot validation ────────────────────────────────────────────────────
async function validateScreenshots(files, isArchive) {
  if (!isArchive) return { errors: [], perFileErrors: [] }

  const errors = []
  const perFileErrors = Array.from({ length: files.length }, () => '')

  if (files.length < 1) errors.push('At least one screenshot is required for archives.')
  if (files.length > 5) errors.push('Maximum 5 screenshots are allowed.')

  await Promise.all(
    files.map(async (file, index) => {
      const typeErrors = []
      const extension = getExtension(file.name)
      const mime = String(file.type || '').toLowerCase()

      if (!IMAGE_MIME.has(mime) && !IMAGE_EXTENSIONS.has(extension)) {
        typeErrors.push('Must be JPG, PNG, or WEBP.')
      }
      if (file.size > SCREENSHOT_MAX_BYTES) {
        typeErrors.push('Must be 10MB or less.')
      }
      if (typeErrors.length === 0) {
        try {
          const dimensions = await readImageDimensions(file)
          if (dimensions.width < 1280 || dimensions.height < 720) {
            typeErrors.push('Minimum resolution is 1280×720.')
          }
        } catch {
          typeErrors.push('Could not read screenshot resolution.')
        }
      }
      if (typeErrors.length > 0) {
        perFileErrors[index] = typeErrors.join(' ')
      }
    })
  )

  if (perFileErrors.some(Boolean)) {
    errors.push('One or more screenshots are invalid.')
  }

  return { errors, perFileErrors }
}

// ─── Hook ─────────────────────────────────────────────────────────────────────
/**
 * useFileValidation
 *
 * Runs async validation on the primary file and screenshots,
 * maintains preview URL lifecycle (revokes on change/unmount),
 * and exposes derived state for the upload UI.
 *
 * @param {File|null} primaryFile
 * @param {File[]}    screenshots
 * @param {boolean}   isArchive   - derived from primaryType === 'archive'
 */
export default function useFileValidation(primaryFile, screenshots, isArchive) {
  const [primaryType, setPrimaryType] = useState('unknown')
  const [primaryErrors, setPrimaryErrors] = useState([])
  const [primaryWarnings, setPrimaryWarnings] = useState([])
  const [fileMetadata, setFileMetadata] = useState({ resolution: '—', size: '—', type: '—' })
  const [primaryPreviewUrl, setPrimaryPreviewUrl] = useState('')

  const [screenshotErrors, setScreenshotErrors] = useState([])
  const [screenshotPerFileErrors, setScreenshotPerFileErrors] = useState([])

  const primaryRunRef = useRef(0)
  const screenshotRunRef = useRef(0)
  const effectiveIsArchive = typeof isArchive === 'boolean'
    ? isArchive
    : detectFileType(primaryFile) === 'archive'

  // Primary file validation
  useEffect(() => {
    primaryRunRef.current += 1
    const runId = primaryRunRef.current
    let cancelled = false

    ;(async () => {
      const result = await validatePrimaryFile(primaryFile)
      if (cancelled || runId !== primaryRunRef.current) return

      setPrimaryType(result.type)
      setPrimaryWarnings(result.warnings)
      setPrimaryErrors(result.errors)
      setFileMetadata(result.metadata)

      setPrimaryPreviewUrl((current) => {
        if (current) URL.revokeObjectURL(current)
        return result.previewUrl
      })
    })()

    return () => {
      cancelled = true
    }
  }, [primaryFile])

  // Screenshot validation
  useEffect(() => {
    screenshotRunRef.current += 1
    const runId = screenshotRunRef.current
    let cancelled = false

    ;(async () => {
      const result = await validateScreenshots(screenshots, effectiveIsArchive)
      if (cancelled || runId !== screenshotRunRef.current) return
      setScreenshotErrors(result.errors)
      setScreenshotPerFileErrors(result.perFileErrors)
    })()

    return () => {
      cancelled = true
    }
  }, [screenshots, effectiveIsArchive])

  // Clear screenshots when file changes to a non-archive
  useEffect(() => {
    if (!effectiveIsArchive) {
      setScreenshotErrors([])
      setScreenshotPerFileErrors([])
    }
  }, [effectiveIsArchive])

  // Revoke preview URL on unmount
  useEffect(() => {
    return () => {
      if (primaryPreviewUrl) URL.revokeObjectURL(primaryPreviewUrl)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  return {
    primaryType,
    primaryErrors,
    primaryWarnings,
    fileMetadata,
    primaryPreviewUrl,
    screenshotErrors,
    screenshotPerFileErrors,
  }
}

/** Standalone for use outside the hook if needed */
export { validatePrimaryFile, validateScreenshots }
