import { commitImage } from "@/lib/media-manager/commit"
import { MEDIA_FILE_BASE } from "@/lib/media-manager/file-names"
import { revokeStagedImage } from "@/lib/media-manager/stage"
import type { StagedImage } from "@/lib/media-manager/types"

export interface DoctorPendingProfileSlot {
  type: "profile"
  staged: StagedImage
}

export interface DoctorPendingBeforeAfterSlot {
  type: "before-after"
  index: number
  staged: StagedImage
}

export type DoctorPendingSlot = DoctorPendingProfileSlot | DoctorPendingBeforeAfterSlot

export interface DoctorPendingImages {
  profile?: StagedImage | null
  beforeAfter: Map<number, StagedImage>
}

export function createEmptyDoctorPendingImages(): DoctorPendingImages {
  return { profile: null, beforeAfter: new Map() }
}

export interface DoctorFormImageSlice<TBasic, TCase> {
  basicInfo: TBasic
  beforeAfter: TCase[]
}

export interface CommitPendingDoctorImagesOptions {
  doctorName: string
  doctorId?: string
  pending: DoctorPendingImages
}

/** Upload all pending doctor images, merge URLs into form slice, clear pending. */
export async function commitPendingDoctorImages<TBasic extends { image: string; imagePublicId: string }, TCase extends { image: string; imagePublicId: string }>(
  slice: DoctorFormImageSlice<TBasic, TCase>,
  options: CommitPendingDoctorImagesOptions
): Promise<DoctorFormImageSlice<TBasic, TCase>> {
  const doctorName = options.doctorName.trim()
  if (!doctorName) {
    throw new Error("Doctor name is required before saving images.")
  }

  let basicInfo = { ...slice.basicInfo }
  const beforeAfter = slice.beforeAfter.map((item) => ({ ...item }))

  if (options.pending.profile) {
    const committed = await commitImage({
      staged: options.pending.profile,
      doctorName,
      section: "doctor-photo",
      fileBaseName: MEDIA_FILE_BASE.doctorPhoto,
      doctorId: options.doctorId,
    })
    revokeStagedImage(options.pending.profile)
    basicInfo = {
      ...basicInfo,
      image: committed.url,
      imagePublicId: committed.publicId,
    }
    options.pending.profile = null
  }

  const indices = [...options.pending.beforeAfter.keys()].sort((a, b) => a - b)
  for (const index of indices) {
    const staged = options.pending.beforeAfter.get(index)
    if (!staged) continue
    const committed = await commitImage({
      staged,
      doctorName,
      section: "before-after",
      fileBaseName: MEDIA_FILE_BASE.beforeAfter,
      fileIndex: index,
      doctorId: options.doctorId,
    })
    revokeStagedImage(staged)
    options.pending.beforeAfter.delete(index)
    if (beforeAfter[index]) {
      beforeAfter[index] = {
        ...beforeAfter[index],
        image: committed.url,
        imagePublicId: committed.publicId,
      }
    }
  }

  return { basicInfo, beforeAfter }
}

export function clearDoctorPendingImages(pending: DoctorPendingImages) {
  if (pending.profile) revokeStagedImage(pending.profile)
  pending.profile = null
  for (const staged of pending.beforeAfter.values()) {
    revokeStagedImage(staged)
  }
  pending.beforeAfter.clear()
}
