﻿import { randomUUID } from "crypto"
import { NextResponse } from "next/server"
import { touchUpdatedAt } from "@/lib/content-audit"
import { Prisma } from "@prisma/client"
import { prisma } from "@/lib/prisma"
import { getCurrentUser, isAllowedRole } from "@/lib/user"
import {
  HOME_PAGE_ENTITY_KEY,
  HOME_PAGE_LOCALE_CODES,
  type HomePageLocaleCode,
} from "@/lib/pages/home/locales"
import {
  parseHomePageJsonForStorage,
  parseHomePagePutBody,
  type HomePageSectionKey,
} from "@/lib/pages/home/validate-payload"
import { createEmptyHomePageFormState, type HomePageFormStateShape } from "@/lib/pages/home/form-types"
import { normalizeHomePageLocaleImagesForStorage } from "@/lib/pages/home/shared-images"
import { deleteImage, extractMediaKeyFromUrl } from "@/lib/r2-storage"
import {
  getPersistedMediaValidationError,
  normalizePersistedMediaInPayload,
} from "@/lib/media-manager/validate-persisted-payload"

export const dynamic = "force-dynamic"
export const revalidate = 0

const NO_CACHE_HEADERS = {
  "Cache-Control": "no-store, no-cache, must-revalidate, proxy-revalidate",
  Pragma: "no-cache",
  Expires: "0",
}

type UnknownRecord = Record<string, unknown>

function isRecord(value: unknown): value is UnknownRecord {
  return value !== null && typeof value === "object" && !Array.isArray(value)
}

function collectImageUrls(node: unknown, acc: Set<string>) {
  if (Array.isArray(node)) {
    for (const item of node) collectImageUrls(item, acc)
    return
  }
  if (!isRecord(node)) return

  for (const [key, value] of Object.entries(node)) {
    if ((key === "image" || key === "avatar") && typeof value === "string") {
      const trimmed = value.trim()
      if (trimmed) acc.add(trimmed)
      continue
    }
    if (Array.isArray(value) || isRecord(value)) {
      collectImageUrls(value, acc)
    }
  }
}

function collectHomeImagePublicIds(state: HomePageFormStateShape): Set<string> {
  const urls = new Set<string>()
  collectImageUrls(state, urls)
  const ids = new Set<string>()
  for (const url of urls) {
    const id = extractMediaKeyFromUrl(url, { prefix: "home-page" })
    if (id?.startsWith("home-page/")) ids.add(id)
  }
  return ids
}

async function ensureAdmin() {
  const user = await getCurrentUser()
  if (!user) {
    return { ok: false as const, res: NextResponse.json({ error: "Unauthorized" }, { status: 401, headers: NO_CACHE_HEADERS }) }
  }
  if (!isAllowedRole(user.role, ["admin"])) {
    return { ok: false as const, res: NextResponse.json({ error: "Forbidden" }, { status: 403, headers: NO_CACHE_HEADERS }) }
  }
  return { ok: true as const, user }
}

function fail(message: string, status = 400) {
  return NextResponse.json({ success: false as const, error: message }, { status, headers: NO_CACHE_HEADERS })
}

function rowToFormState(contentJson: unknown): HomePageFormStateShape {
  // contentJson is stored as a string in the database. If it's a string, attempt to parse it.
  let parsed: unknown = contentJson
  if (typeof contentJson === "string") {
    try {
      parsed = JSON.parse(contentJson)
    } catch {
      parsed = undefined
    }
  }
  return parseHomePageJsonForStorage(parsed).data
}

function buildMergedLocalesForSectionSave(
  existingByLocale: Partial<Record<HomePageLocaleCode, HomePageFormStateShape>>,
  incomingLocales: Record<string, HomePageFormStateShape>,
  sectionKey: HomePageSectionKey
): Record<HomePageLocaleCode, HomePageFormStateShape> {
  const next: Record<HomePageLocaleCode, HomePageFormStateShape> = {
    en: createEmptyHomePageFormState(),
    tr: createEmptyHomePageFormState(),
    ar: createEmptyHomePageFormState(),
  }

  for (const locale of HOME_PAGE_LOCALE_CODES) {
    const base = existingByLocale[locale] ?? createEmptyHomePageFormState()
    const incoming = incomingLocales[locale] ?? base
    next[locale] = {
      ...base,
      [sectionKey]: incoming[sectionKey],
    }
  }

  return next
}

export async function GET() {
  const auth = await ensureAdmin()
  if (!auth.ok) return auth.res

  try {
    const rows = await prisma.homePageLocale.findMany({
      where: { entityKey: HOME_PAGE_ENTITY_KEY },
      orderBy: { locale: "asc" },
    })

    const locales: Partial<Record<HomePageLocaleCode, HomePageFormStateShape>> = {}
    for (const row of rows) {
      if (!HOME_PAGE_LOCALE_CODES.includes(row.locale as HomePageLocaleCode)) continue
      const code = row.locale as HomePageLocaleCode
      locales[code] = rowToFormState(row.contentJson)
    }

    return NextResponse.json(
      { success: true as const, locales: normalizeHomePageLocaleImagesForStorage(locales) },
      { headers: NO_CACHE_HEADERS }
    )
  } catch (error) {
    console.error("[admin/home-page] GET error:", error)
    return NextResponse.json(
      { success: false as const, error: "Failed to load home page" },
      { status: 500, headers: NO_CACHE_HEADERS }
    )
  }
}

export async function PUT(req: Request) {
  const auth = await ensureAdmin()
  if (!auth.ok) return auth.res

  let body: unknown
  try {
    body = await req.json()
  } catch {
    return fail("Invalid JSON body")
  }

  const normalizedBody = normalizePersistedMediaInPayload(body)
  const mediaError = getPersistedMediaValidationError(normalizedBody)
  if (mediaError) return fail(mediaError)

  const parsed = parseHomePagePutBody(normalizedBody)
  if (!parsed.ok) return fail(parsed.error)

  try {
    const existingRows = await prisma.homePageLocale.findMany({
      where: { entityKey: HOME_PAGE_ENTITY_KEY },
      select: { locale: true, contentJson: true },
    })

    const existingByLocale: Partial<Record<HomePageLocaleCode, HomePageFormStateShape>> = {}
    for (const row of existingRows) {
      if (!HOME_PAGE_LOCALE_CODES.includes(row.locale as HomePageLocaleCode)) continue
      existingByLocale[row.locale as HomePageLocaleCode] = rowToFormState(row.contentJson)
    }

    const localesToPersist =
      parsed.data.sectionKey
        ? buildMergedLocalesForSectionSave(existingByLocale, parsed.data.locales, parsed.data.sectionKey)
        : (parsed.data.locales as Record<HomePageLocaleCode, HomePageFormStateShape>)

    const normalizedLocales = normalizeHomePageLocaleImagesForStorage(localesToPersist)

    const previousPublicIds = new Set<string>()
    for (const row of existingRows) {
      const state = rowToFormState(row.contentJson)
      for (const id of collectHomeImagePublicIds(state)) previousPublicIds.add(id)
    }

    const nextPublicIds = new Set<string>()
    for (const state of Object.values(normalizedLocales)) {
      if (!state) continue
      for (const id of collectHomeImagePublicIds(state)) nextPublicIds.add(id)
    }

    const localeNow = new Date()
    const ops = (Object.entries(normalizedLocales) as [HomePageLocaleCode, HomePageFormStateShape][]).map(
      ([locale, state]) =>
        prisma.homePageLocale.upsert({
          where: {
            entityKey_locale: {
              entityKey: HOME_PAGE_ENTITY_KEY,
              locale,
            },
          },
          create: {
            id: randomUUID(),
            updatedAt: localeNow,
            entityKey: HOME_PAGE_ENTITY_KEY,
            locale,
            contentJson: JSON.stringify(state),
          },
          update: {
            ...touchUpdatedAt(),
            contentJson: JSON.stringify(state),
          },
        })
    )
    await prisma.$transaction(ops)

    const stalePublicIds = [...previousPublicIds].filter((id) => !nextPublicIds.has(id))
    if (stalePublicIds.length > 0) {
      await Promise.allSettled(stalePublicIds.map((id) => deleteImage(id)))
    }
  } catch (error) {
    console.error("[admin/home-page] PUT error:", error)
    return NextResponse.json(
      { success: false as const, error: "Failed to save home page" },
      { status: 500, headers: NO_CACHE_HEADERS }
    )
  }

  return NextResponse.json({ success: true as const }, { headers: NO_CACHE_HEADERS })
}
