import { compressVideo } from './compress'
import { resizeImage } from './resize'
import type { MediaAsset, ProcessOptions, RawAsset } from './types'

export type ProcessOutcome =
  | { ok: true; asset: MediaAsset }
  | { ok: false; reason: 'aborted' | 'video_too_large' | 'video_failed'; message: string }

/** Routes a raw picked asset through the right processor (resize vs compress). */
export async function processMedia(
  raw: RawAsset,
  opts: ProcessOptions
): Promise<ProcessOutcome> {
  if (opts.signal?.aborted) {
    return { ok: false, reason: 'aborted', message: 'Cancelled' }
  }

  if (raw.kind === 'photo') {
    const next = await resizeImage(raw, opts)
    const asset: MediaAsset = {
      ...next,
      altText: null,
      originalUri: next.uri !== raw.uri ? raw.uri : undefined,
    }
    return { ok: true, asset }
  }

  const result = await compressVideo(raw, opts)
  if (result.ok) {
    const asset: MediaAsset = {
      ...result.asset,
      altText: null,
      originalUri: result.compressed ? raw.uri : undefined,
    }
    return { ok: true, asset }
  }

  if (result.reason === 'too_large') {
    const mb = result.sizeMb.toFixed(1)
    return {
      ok: false,
      reason: 'video_too_large',
      message: `Video is ${mb} MB after compression — this instance caps videos at ${result.limitMb} MB.`,
    }
  }
  if (result.reason === 'aborted') {
    return { ok: false, reason: 'aborted', message: 'Cancelled' }
  }
  return {
    ok: false,
    reason: 'video_failed',
    message: 'Could not prepare video for upload.',
  }
}

/** Processes a batch in order. Video errors surface as outcomes; callers
 *  decide whether to discard the item or abort the batch. */
export async function processMediaBatch(
  items: RawAsset[],
  opts: ProcessOptions
): Promise<ProcessOutcome[]> {
  const out: ProcessOutcome[] = []
  for (const raw of items) {
    if (opts.signal?.aborted) {
      out.push({ ok: false, reason: 'aborted', message: 'Cancelled' })
      continue
    }
    out.push(await processMedia(raw, opts))
  }
  return out
}
