import { relocateObjectsUnderPrefix } from "@/lib/r2-storage"
import { rewriteLegacyMediaPublicUrl } from "@/lib/r2-media-url"

type JsonRecord = Record<string, unknown>

/** Normalize an R2 prefix (no leading/trailing slashes). */
export function normalizeMediaBase(base: string): string {
  return base.trim().replace(/^\/+|\/+$/g, "")
}

/** Deduplicate media base prefixes while preserving order. */
export function uniqueMediaBases(bases: Array<string | null | undefined>): string[] {
  const seen = new Set<string>()
  const out: string[] = []
  for (const raw of bases) {
    const normalized = typeof raw === "string" ? normalizeMediaBase(raw) : ""
    if (!normalized || seen.has(normalized)) continue
    seen.add(normalized)
    out.push(normalized)
  }
  return out
}

/** Recursively replace `oldBase` with `newBase` in strings (URLs, media keys, HTML). */
export function rewriteMediaPaths(value: unknown, oldBase: string, newBase: string): unknown {
  const oldNorm = normalizeMediaBase(oldBase)
  const newNorm = normalizeMediaBase(newBase)
  if (!oldNorm || !newNorm || oldNorm === newNorm) return value

  if (value === null || value === undefined) return value
  if (typeof value === "string") {
    let next = rewriteLegacyMediaPublicUrl(value)
    if (!next.includes(oldNorm)) return next
    next = next.split(oldNorm).join(newNorm)
    return next
  }
  if (Array.isArray(value)) {
    return value.map((item) => rewriteMediaPaths(item, oldNorm, newNorm))
  }
  if (typeof value === "object") {
    const record = value as JsonRecord
    const out: JsonRecord = {}
    for (const [key, raw] of Object.entries(record)) {
      out[key] = rewriteMediaPaths(raw, oldNorm, newNorm)
    }
    return out
  }
  return value
}

/** Apply multiple old-base → new-base rewrites (e.g. slug folder + legacy contentImageFolder). */
export function rewriteMediaPathsMulti(
  value: unknown,
  oldBases: Array<string | null | undefined>,
  newBase: string
): unknown {
  const newNorm = normalizeMediaBase(newBase)
  let result = value
  for (const oldBase of uniqueMediaBases(oldBases)) {
    if (oldBase === newNorm) continue
    result = rewriteMediaPaths(result, oldBase, newNorm)
  }
  return result
}

/** Move every object under each old prefix into `newBase` (same relative paths). */
export async function relocateMediaBases(
  oldBases: Array<string | null | undefined>,
  newBase: string
): Promise<{ moved: number }> {
  const newNorm = normalizeMediaBase(newBase)
  if (!newNorm) return { moved: 0 }

  let moved = 0
  for (const oldBase of uniqueMediaBases(oldBases)) {
    if (oldBase === newNorm) continue
    const result = await relocateObjectsUnderPrefix(oldBase, newNorm)
    moved += result.moved
  }
  return { moved }
}

import { toArticleFolderSegment } from "@/lib/media-manager/paths"

/** Article-specific old prefixes that may contain media (slug path + legacy folder). */
export function collectArticleOldMediaBases(input: {
  slug: string
  contentImageFolder?: string | null
}): string[] {
  const slugBase = `articles/${toArticleFolderSegment(input.slug)}`
  return uniqueMediaBases([slugBase, input.contentImageFolder])
}
