/** Pure R2 media URL / key helpers — safe for client + server (no SDK). */

export type MediaKeyPrefix = string

/** Canonical site origin — never use the legacy `media.` subdomain for public URLs. */
export const CANONICAL_MEDIA_PUBLIC_ORIGIN = "https://livistmedical.com"

/** Default public base when env is missing or invalid (Worker serves R2 under `/storage`). */
export const DEFAULT_R2_PUBLIC_BASE_URL = `${CANONICAL_MEDIA_PUBLIC_ORIGIN}/storage`

const LEGACY_MEDIA_HOSTNAMES = new Set(["media.livistmedical.com"])

function stripTrailingSlashes(value: string): string {
  return value.replace(/\/+$/, "")
}

function publicBasePathSegments(): string[] {
  try {
    return new URL(DEFAULT_R2_PUBLIC_BASE_URL).pathname.split("/").filter(Boolean)
  } catch {
    return ["storage"]
  }
}

function ensurePublicBasePathOnUrl(u: URL): void {
  const required = publicBasePathSegments()
  if (required.length === 0) return
  const current = u.pathname.split("/").filter(Boolean)
  const hasPrefix = required.every((seg, i) => current[i] === seg)
  if (hasPrefix) return
  u.pathname = `/${[...required, ...current].join("/")}`
}

/**
 * Normalize `R2_PUBLIC_BASE_URL` / `NEXT_PUBLIC_R2_PUBLIC_BASE_URL`.
 * Rewrites legacy `media.livistmedical.com` (R2 custom domain) to `livistmedical.com`.
 */
export function resolveR2PublicBaseUrl(
  raw?: string | null,
  options: { fallback?: string } = {}
): string {
  const fallback = options.fallback ?? DEFAULT_R2_PUBLIC_BASE_URL
  const trimmed = typeof raw === "string" ? raw.trim() : ""
  if (!trimmed) return fallback

  try {
    const u = new URL(trimmed)
    const host = u.hostname.toLowerCase()
    const wasLegacyMediaHost = LEGACY_MEDIA_HOSTNAMES.has(host)
    if (wasLegacyMediaHost) {
      u.hostname = "livistmedical.com"
      ensurePublicBasePathOnUrl(u)
    }
    if (u.hostname === "livistmedical.com" && u.protocol === "http:") {
      u.protocol = "https:"
    }
    const path = stripTrailingSlashes(u.pathname)
    if (wasLegacyMediaHost && !path) {
      return DEFAULT_R2_PUBLIC_BASE_URL
    }
    return `${u.origin}${path || ""}` || fallback
  } catch {
    return fallback
  }
}

/**
 * Active public base for all uploads and URL building.
 *
 * Production always uses `https://livistmedical.com/storage` — env vars cannot
 * override with legacy `media.livistmedical.com` (R2 custom domain).
 *
 * Local override: set `ALLOW_LOCAL_R2_PUBLIC_BASE=1` and e.g.
 * `R2_PUBLIC_BASE_URL=http://localhost:3000/storage`
 */
export function getR2PublicBaseUrl(): string {
  const allowLocalOverride = process.env.ALLOW_LOCAL_R2_PUBLIC_BASE === "1"
  if (allowLocalOverride) {
    const resolved = resolveR2PublicBaseUrl(
      process.env.R2_PUBLIC_BASE_URL ?? process.env.NEXT_PUBLIC_R2_PUBLIC_BASE_URL
    )
    if (!resolved.includes("media.livistmedical.com")) {
      return resolved
    }
  }
  return DEFAULT_R2_PUBLIC_BASE_URL
}

/** Rewrite a stored URL that still points at the legacy `media.` host. */
export function rewriteLegacyMediaPublicUrl(url: string): string {
  const raw = url.trim()
  if (!raw || !/^https?:\/\//i.test(raw)) return raw
  try {
    const u = new URL(raw)
    if (!LEGACY_MEDIA_HOSTNAMES.has(u.hostname.toLowerCase())) return raw
    u.hostname = "livistmedical.com"
    if (u.protocol === "http:") u.protocol = "https:"
    ensurePublicBasePathOnUrl(u)
    return u.toString()
  } catch {
    return raw
  }
}

function matchesPrefix(mediaKey: string, prefix?: string): boolean {
  const normalized = prefix?.trim().replace(/\/+$/, "")
  if (!normalized) return true
  return mediaKey === normalized || mediaKey.startsWith(`${normalized}/`)
}

/** Path segments → media key (path without file extension). */
function mediaKeyFromPathSegments(segments: string[]): string | null {
  if (segments.length === 0) return null

  const filename = segments[segments.length - 1]
  const dotIndex = filename.lastIndexOf(".")
  const nameWithoutExt = dotIndex > 0 ? filename.slice(0, dotIndex) : filename
  if (!nameWithoutExt) return null

  const mediaKey = [...segments.slice(0, -1), nameWithoutExt].join("/")
  return mediaKey || null
}

/** Legacy CDN URLs that used an `/upload/` path segment (pre-R2 content). */
function extractMediaKeyFromLegacyUploadPath(
  raw: string,
  options: { prefix?: MediaKeyPrefix } = {}
): string | null {
  const marker = "/upload/"
  const uploadIndex = raw.indexOf(marker)
  if (uploadIndex === -1) return null

  const afterUpload = raw.slice(uploadIndex + marker.length)
  const segments = afterUpload.split("/").filter(Boolean)
  if (segments.length === 0) return null

  const maybeVersion = segments[0]
  const withoutVersion = /^v\d+$/.test(maybeVersion) ? segments.slice(1) : segments
  const mediaKey = mediaKeyFromPathSegments(withoutVersion)
  if (!mediaKey) return null
  if (!matchesPrefix(mediaKey, options.prefix)) return null
  return mediaKey
}

/** Drop Worker/public-base path prefix (e.g. `/storage`) before resolving object keys. */
function objectPathSegmentsFromPublicUrl(url: URL): string[] {
  const segments = url.pathname.split("/").filter(Boolean)
  try {
    const basePath = new URL(getR2PublicBaseUrl()).pathname.split("/").filter(Boolean)
    if (basePath.length > 0) {
      let i = 0
      while (i < basePath.length && i < segments.length && segments[i] === basePath[i]) {
        i += 1
      }
      if (i === basePath.length) return segments.slice(i)
    }
  } catch {
    /* ignore */
  }
  if (segments[0] === "storage") return segments.slice(1)
  return segments
}

function extractMediaKeyFromPublicUrl(
  raw: string,
  options: { prefix?: MediaKeyPrefix } = {}
): string | null {
  try {
    const u = new URL(rewriteLegacyMediaPublicUrl(raw))
    const segments = objectPathSegmentsFromPublicUrl(u)
    const mediaKey = mediaKeyFromPathSegments(segments)
    if (!mediaKey) return null
    if (!matchesPrefix(mediaKey, options.prefix)) return null
    return mediaKey
  } catch {
    return null
  }
}

/** Resolve a stored media key from a public image URL. */
export function extractMediaKeyFromUrl(
  url?: string | null,
  options: { prefix?: MediaKeyPrefix } = {}
): string | null {
  const raw = typeof url === "string" ? url.trim() : ""
  if (!raw) return null

  const fromLegacy = extractMediaKeyFromLegacyUploadPath(raw, options)
  if (fromLegacy) return fromLegacy

  return extractMediaKeyFromPublicUrl(raw, options)
}

/** Full R2 object key (with extension) from a public URL. */
export function extractObjectKeyFromUrl(url?: string | null): string | null {
  const raw = typeof url === "string" ? url.trim() : ""
  if (!raw) return null
  try {
    const segments = objectPathSegmentsFromPublicUrl(new URL(rewriteLegacyMediaPublicUrl(raw)))
    return segments.length > 0 ? segments.join("/") : null
  } catch {
    return null
  }
}

export function buildPublicUrl(objectKey: string): string {
  const base = getR2PublicBaseUrl()
  const key = objectKey.replace(/^\/+/, "")
  return `${base}/${key}`
}

const IMAGE_EXT_RE = /\.(webp|jpe?g|png|gif|avif|svg)(?:\?|#|$)/i

function extensionFromUrl(url: string): string {
  const match = url.match(IMAGE_EXT_RE)
  if (!match) return "webp"
  const ext = match[1].toLowerCase()
  return ext === "jpeg" ? "jpg" : ext
}

/**
 * Single canonical public URL for a stored image.
 * Prefer rebuilding from the R2 object key (via URL or `*PublicId`) so DB legacy hosts
 * (`media.livistmedical.com`, missing `/storage`, etc.) never leak to clients.
 */
export function canonicalPublicMediaUrl(
  storedUrl?: string | null,
  mediaKeyOrPublicId?: string | null
): string {
  const url = typeof storedUrl === "string" ? storedUrl.trim() : ""
  const keyHint = typeof mediaKeyOrPublicId === "string" ? mediaKeyOrPublicId.trim() : ""

  const objectKeyFromUrl = url ? extractObjectKeyFromUrl(url) : null
  if (objectKeyFromUrl) return buildPublicUrl(objectKeyFromUrl)

  const mediaKey = keyHint || (url ? extractMediaKeyFromUrl(url) : null)
  if (mediaKey) {
    const ext = url ? extensionFromUrl(url) : "webp"
    return buildPublicUrl(`${mediaKey}.${ext}`)
  }

  if (url) return rewriteLegacyMediaPublicUrl(url)
  return ""
}

/** Rewrite `<img src="...">` in HTML to canonical `/storage/` URLs. */
export function normalizeMediaUrlsInHtml(html?: string | null): string {
  const raw = typeof html === "string" ? html : ""
  if (!raw.trim()) return raw

  return raw.replace(
    /(<img\b[^>]*\bsrc\s*=\s*["'])([^"']+)(["'][^>]*>)/gi,
    (_match, prefix: string, src: string, suffix: string) => {
      const trimmed = src.trim()
      if (!/^https?:\/\//i.test(trimmed)) return `${prefix}${src}${suffix}`
      return `${prefix}${canonicalPublicMediaUrl(trimmed)}${suffix}`
    }
  )
}

/** Media keys referenced by `<img src="...">` in HTML. */
export function extractMediaKeysFromHtml(
  html?: string | null,
  options: { prefix?: MediaKeyPrefix } = {}
): Set<string> {
  const out = new Set<string>()
  const raw = typeof html === "string" ? html : ""
  if (!raw.trim()) return out

  const imgSrcRegex = /<img\b[^>]*\bsrc\s*=\s*["']([^"']+)["'][^>]*>/gi
  let match: RegExpExecArray | null = null
  while ((match = imgSrcRegex.exec(raw)) !== null) {
    const src = match[1]
    const mediaKey = extractMediaKeyFromUrl(src, options)
    if (mediaKey) out.add(mediaKey)
  }
  return out
}

/** Media keys in persisted article HTML (main + locale bodies). */
export function collectBaselineInlineImageKeysFromArticleApiPayload(payload: unknown): Set<string> {
  const out = new Set<string>()
  if (!payload || typeof payload !== "object") return out
  const a = payload as Record<string, unknown>
  const addHtml = (html: unknown) => {
    if (typeof html !== "string") return
    extractMediaKeysFromHtml(html, { prefix: "articles" }).forEach((key) => out.add(key))
  }
  addHtml(a.content)
  const tr = a.translations
  if (tr && typeof tr === "object") {
    for (const loc of ["en", "ar", "tr"] as const) {
      const block = (tr as Record<string, unknown>)[loc]
      if (block && typeof block === "object" && block !== null) {
        addHtml((block as Record<string, unknown>).content)
      }
    }
  }
  return out
}
