/** Detected image MIME types supported by the magic-byte gate. */
export type DetectedImageMime =
  | 'image/jpeg'
  | 'image/png'
  | 'image/webp'
  | 'image/avif'
  | 'image/gif'

const TEXT_DECODER = new TextDecoder('latin1')

function bytesToAscii(bytes: Uint8Array, start: number, length: number): string {
  return TEXT_DECODER.decode(bytes.subarray(start, start + length))
}

function startsWithAscii(bytes: Uint8Array, start: number, literal: string): boolean {
  if (bytes.length < start + literal.length) return false
  for (let i = 0; i < literal.length; i++) {
    if (bytes[start + i] !== literal.charCodeAt(i)) return false
  }
  return true
}

function isDangerousTextHeader(header: Uint8Array): boolean {
  const sample = TEXT_DECODER.decode(header.subarray(0, Math.min(header.length, 256))).trimStart().toLowerCase()
  if (sample.startsWith('<svg')) return true
  if (sample.startsWith('<html')) return true
  if (sample.startsWith('<!doctype html')) return true
  if (sample.startsWith('<!doctype svg')) return true
  if (sample.startsWith('<?xml')) return true
  if (sample.includes('<script')) return true
  return false
}

function isJpeg(header: Uint8Array): boolean {
  return header.length >= 3 && header[0] === 0xff && header[1] === 0xd8 && header[2] === 0xff
}

function isPng(header: Uint8Array): boolean {
  return (
    header.length >= 8 &&
    header[0] === 0x89 &&
    header[1] === 0x50 &&
    header[2] === 0x4e &&
    header[3] === 0x47 &&
    header[4] === 0x0d &&
    header[5] === 0x0a &&
    header[6] === 0x1a &&
    header[7] === 0x0a
  )
}

function isGif(header: Uint8Array): boolean {
  if (header.length < 6) return false
  const tag = bytesToAscii(header, 0, 6)
  return tag === 'GIF87a' || tag === 'GIF89a'
}

function isWebp(header: Uint8Array): boolean {
  return (
    header.length >= 12 &&
    bytesToAscii(header, 0, 4) === 'RIFF' &&
    bytesToAscii(header, 8, 4) === 'WEBP'
  )
}

/** Strict AVIF brand check: major or compatible brand must be `avif` or `avis`. Bare `ftyp` alone is rejected. */
function isStrictAvif(header: Uint8Array): boolean {
  if (header.length < 12 || !startsWithAscii(header, 4, 'ftyp')) return false

  const brands: string[] = [bytesToAscii(header, 8, 4)]
  for (let offset = 16; offset + 4 <= header.length; offset += 4) {
    brands.push(bytesToAscii(header, offset, 4))
  }

  return brands.some((brand) => brand === 'avif' || brand === 'avis')
}

/**
 * Detect image MIME type from the first bytes of a file.
 * Header-only, zero-dep. Rejects SVG/HTML/script/XML and loose bare-`ftyp` AVIF.
 */
export function detectMimeFromMagicBytes(header: Uint8Array): DetectedImageMime | null {
  if (header.length === 0) return null
  if (isDangerousTextHeader(header)) return null
  if (isJpeg(header)) return 'image/jpeg'
  if (isPng(header)) return 'image/png'
  if (isGif(header)) return 'image/gif'
  if (isWebp(header)) return 'image/webp'
  if (isStrictAvif(header)) return 'image/avif'
  return null
}
