// Pure URL/extension resolution for the save-to-photos flow. Kept free of any
// native-module imports (only `toImageUri` + types) so it is unit-testable in
// isolation — the native download/save lives in `saveToPhotos.ts`.

import type { MediaAttachment } from 'src/lib/api-types'
import { toImageUri } from 'src/lib/media-source'

export type SaveMediaKind = 'image' | 'video'

export type SaveInput = {
  // Preferred: the attachment (kind + downloadable URL are derived from it).
  attachment?: MediaAttachment
  // Or pass an already-resolved uri+kind (the lightbox only knows the uri).
  uri?: string
  kind?: SaveMediaKind
}

export type SaveTarget = { kind: SaveMediaKind; url: string } | { unsupported: true }

const VIDEO_EXTS = ['mp4', 'mov', 'm4v', 'webm']
const IMAGE_EXTS = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'heic', 'heif']

function stripQuery(url: string): string {
  return url.split('?')[0].split('#')[0]
}

function isHls(url: string): boolean {
  return stripQuery(url).toLowerCase().endsWith('.m3u8')
}

/** Pick the downloadable URL + kind from the input. Images prefer `remote_url`
 *  (via `toImageUri`) for federated media; video uses the progressive `url`
 *  (never `remote_url`, which may be an undecodable upstream format). HLS
 *  manifests can't be saved as one file → `unsupported`. */
export function resolveSaveTarget(input: SaveInput): SaveTarget {
  if (input.uri && input.kind) {
    if (isHls(input.uri)) return { unsupported: true }
    return { kind: input.kind, url: input.uri }
  }
  const a = input.attachment
  if (!a) return { unsupported: true }
  const isVideo = a.type === 'video' || a.type === 'gifv'
  if (isVideo) {
    if (!a.url || isHls(a.url)) return { unsupported: true }
    return { kind: 'video', url: a.url }
  }
  const url = toImageUri(a)
  if (!url) return { unsupported: true }
  return { kind: 'image', url }
}

/** Choose a file extension. `saveToLibraryAsync` infers the asset type from the
 *  extension, so it must be correct for the media kind. */
export function inferExtension(url: string, kind: SaveMediaKind): string {
  const ext = stripQuery(url)
    .match(/\.([a-z0-9]{1,5})$/i)?.[1]
    ?.toLowerCase()
  const known = kind === 'video' ? VIDEO_EXTS : IMAGE_EXTS
  if (ext && known.includes(ext)) return ext
  return kind === 'video' ? 'mp4' : 'jpg'
}
