﻿import { extractMediaKeyFromUrl } from "@/lib/r2-storage"

type JsonRecord = Record<string, unknown>
type BasicInfoLocaleFields = {
  startingFromPrice: string
  duration: string
  hospitalStay: string
  recovery: string
}

export const PROCEDURE_LOCALES = ["en", "ar", "tr"] as const
export type ProcedureLocale = (typeof PROCEDURE_LOCALES)[number]

export function parseProcedureLocale(value: unknown): ProcedureLocale {
  if (value === "ar" || value === "tr") return value
  return "en"
}

/** Ensures persisted basicInfo JSON always exposes array fields expected by the form. */
export function normalizeProcedureBasicInfoJson(raw: unknown): JsonRecord {
  const record =
    raw && typeof raw === "object" && !Array.isArray(raw) ? (raw as JsonRecord) : {}
  return {
    ...record,
    beforeAfterImages: Array.isArray(record.beforeAfterImages) ? record.beforeAfterImages : [],
  }
}

function defaultBasicInfoLocale(): BasicInfoLocaleFields {
  return {
    startingFromPrice: "",
    duration: "",
    hospitalStay: "",
    recovery: "",
  }
}

export function toProcedureFolderSegment(value: string): string {
  const normalized = value
    .trim()
    .toLowerCase()
    .replace(/[^a-z0-9\s-_]/g, "")
    .replace(/\s+/g, "-")
    .replace(/-+/g, "-")
    .replace(/^[-_]+|[-_]+$/g, "")
  return normalized || "untitled-procedure"
}

export function resolveProcedureImageFolder(input: { slug?: string; name?: string }) {
  const slug = typeof input.slug === "string" ? input.slug.trim() : ""
  const name = typeof input.name === "string" ? input.name.trim() : ""
  const segment = slug || toProcedureFolderSegment(name)
  return `procedures/${segment}`
}

/** R2 prefix root for a procedure slug: `procedures/{slug-segment}`. */
export function procedureMediaBaseForSlug(slug: string): string {
  return `procedures/${toProcedureFolderSegment(slug)}`
}

/** Rewrite stored media keys and public URLs after a slug change. */
export function rewriteProcedureMediaPaths(
  value: unknown,
  oldBase: string,
  newBase: string
): unknown {
  if (oldBase === newBase) return value
  if (value === null || value === undefined) return value
  if (typeof value === "string") {
    if (!value.includes(oldBase)) return value
    return value.split(oldBase).join(newBase)
  }
  if (Array.isArray(value)) {
    return value.map((item) => rewriteProcedureMediaPaths(item, oldBase, newBase))
  }
  if (typeof value === "object") {
    const record = value as JsonRecord
    const out: JsonRecord = {}
    for (const [key, raw] of Object.entries(record)) {
      out[key] = rewriteProcedureMediaPaths(raw, oldBase, newBase)
    }
    return out
  }
  return value
}

export function folderFromMediaKey(mediaKey: string): string | null {
  const id = mediaKey.trim()
  const idx = id.lastIndexOf("/")
  if (idx <= 0) return null
  return id.slice(0, idx)
}

function isImageLikeKey(key: string): boolean {
  const lower = key.toLowerCase()
  return lower.includes("image") || lower.includes("avatar")
}

function shouldSkipValidationPath(key: string): boolean {
  const lower = key.toLowerCase()
  return lower.includes("publicid") || lower === "tags" || lower === "avatar"
}

function mergeImageFieldsFromEnglish(current: unknown, english: unknown): unknown {
  if (Array.isArray(current) && Array.isArray(english)) {
    return current.map((item, idx) => mergeImageFieldsFromEnglish(item, english[idx]))
  }
  if (
    current &&
    typeof current === "object" &&
    english &&
    typeof english === "object" &&
    !Array.isArray(current) &&
    !Array.isArray(english)
  ) {
    const currentRecord = current as JsonRecord
    const englishRecord = english as JsonRecord
    const out: JsonRecord = { ...currentRecord }
    for (const key of Object.keys(englishRecord)) {
      const currentValue = currentRecord[key]
      const englishValue = englishRecord[key]
      if (
        isImageLikeKey(key) &&
        (currentValue === "" || currentValue === null || currentValue === undefined) &&
        typeof englishValue === "string"
      ) {
        out[key] = englishValue
        continue
      }
      out[key] = mergeImageFieldsFromEnglish(currentValue, englishValue)
    }
    return out
  }
  return current
}

export function normalizeProcedureSharedImages(translations: JsonRecord): JsonRecord {
  const en = (translations.en && typeof translations.en === "object" ? translations.en : {}) as JsonRecord
  const next: JsonRecord = { ...translations, en }
  for (const locale of PROCEDURE_LOCALES) {
    const localeValue = (next[locale] && typeof next[locale] === "object" ? next[locale] : {}) as JsonRecord
    next[locale] = locale === "en" ? localeValue : mergeImageFieldsFromEnglish(localeValue, en)
  }
  return next
}

/** Dashboard form slice for ar/tr when no `ProcedureTranslation` row exists (mirrors doctor: no fallback to English in the editor). */
export function emptyProcedureLocaleFormFields(): Record<string, unknown> {
  return {
    name: "",
    description: "",
    overview: {
      eyebrow: "",
      title: "",
      description: "",
      keyTakeawaysTitle: "",
      keyTakeaways: [],
      overviewCardStartingPriceLabel: "",
      overviewCardStartingPriceValue: "",
      overviewCardImage: "",
      overviewCardImagePublicId: "",
    },
    countriesComparison: {
      eyebrow: "",
      title: "",
      subtitle: "",
      bestValueCountryName: "",
      bestValueCountryFlag: "",
      bestValuePrice: "",
      countries: [],
      mainCardLabel: "",
      mainCardValue: "",
      mainCardDescription: "",
      mainCardButtonText: "",
      mainCardButtonLink: "",
      disclaimerText: "",
    },
    process: { eyebrow: "", title: "", subtitle: "", steps: [] },
    benefits: { eyebrow: "", title: "", subtitle: "", benefits: [] },
    beforeAfterSection: {
      eyebrow: "",
      title: "",
      subtitle: "",
      results: [],
      buttonText: "",
      buttonLink: "",
      disclaimerText: "",
    },
    doctorsSectionEyebrow: "",
    doctorsSectionTitle: "",
    stayCity: "",
    basicInfo: defaultBasicInfoLocale(),
    recovery: { eyebrow: "", title: "", subtitle: "", steps: [], noteText: "" },
    packageSection: {
      eyebrow: "",
      title: "",
      subtitle: "",
      features: [],
      startingPriceLabel: "",
      startingPriceValue: "",
      buttonText: "",
      buttonLink: "",
    },
    reviews: [],
    reviewsEyebrow: "",
    reviewsTitle: "",
    faqItems: [],
    faqEyebrow: "",
    faqTitle: "",
    faqSubtitle: "",
    faqButtonText: "",
    faqButtonLink: "",
    related: { eyebrow: "", title: "", buttonText: "", buttonLink: "" },
    cta: {
      eyebrow: "",
      title: "",
      subtitle: "",
      features: [],
      buttonIconKey: "",
      buttonTitle: "",
      buttonSubtitle: "",
      buttonLink: "",
      formTitle: "",
      formSubtitle: "",
      formFullNameLabel: "",
      formPhoneLabel: "",
      formEmailLabel: "",
      formProcedureLabel: "",
      formMessageLabel: "",
      formButtonIconKey: "",
      formButtonText: "",
      formButtonLink: "",
      formEndLabel: "",
    },
    videoSection: {
      eyebrow: "",
      title: "",
      subtitle: "",
      videoLink: "",
    },
  }
}

export function collectMissingEnglishFields(value: unknown): string[] {
  const missing: string[] = []
  walkMissingFields(value, "en", missing)
  return missing
}

function walkMissingFields(value: unknown, path: string, missing: string[]) {
  if (typeof value === "string") {
    if (value.trim() === "") missing.push(path)
    return
  }
  if (typeof value === "number" || typeof value === "boolean") return
  if (value === null || value === undefined) {
    missing.push(path)
    return
  }
  if (Array.isArray(value)) {
    if (value.length === 0) {
      missing.push(path)
      return
    }
    value.forEach((item, idx) => walkMissingFields(item, `${path}[${idx}]`, missing))
    return
  }
  if (typeof value === "object") {
    const record = value as JsonRecord
    for (const key of Object.keys(record)) {
      if (shouldSkipValidationPath(key)) continue
      walkMissingFields(record[key], `${path}.${key}`, missing)
    }
  }
}

export function collectProcedureImagePublicIds(value: unknown): Set<string> {
  const ids = new Set<string>()
  walkForImagePublicIds(value, ids)
  return ids
}

function walkForImagePublicIds(value: unknown, out: Set<string>) {
  if (value === null || value === undefined) return
  if (typeof value === "string") return
  if (Array.isArray(value)) {
    for (const item of value) walkForImagePublicIds(item, out)
    return
  }
  if (typeof value !== "object") return
  const record = value as JsonRecord
  for (const [key, raw] of Object.entries(record)) {
    if (typeof raw === "string") {
      const lower = key.toLowerCase()
      if (lower.includes("publicid")) {
        const id = raw.trim()
        if (id.startsWith("procedures/")) out.add(id)
      } else if (isImageLikeKey(lower)) {
        const fromUrl = extractMediaKeyFromUrl(raw, { prefix: "procedures" })
        if (fromUrl) out.add(fromUrl)
      }
      continue
    }
    walkForImagePublicIds(raw, out)
  }
}
