import { z } from "zod"
import type { ContactQuickStat } from "@/components/dashboard/contact-us/ContactHeroSection"
import type { ContactInfoItem } from "@/components/dashboard/contact-us/ContactInfoSection"
import type { ScheduleEntry } from "@/components/dashboard/contact-us/WorkingHoursSection"
import type { SocialLink } from "@/components/dashboard/contact-us/SocialMediaSection"
import {
  CONTACT_US_PAGE_LOCALE_CODES,
  type ContactUsPageLocaleCode,
} from "@/lib/pages/contact-us/locales"
import { createEmptyContactUsPageFormState } from "@/lib/pages/contact-us/form-types"

const CONTACT_US_PAGE_SECTION_KEYS = [
  "hero",
  "contactInfo",
  "contactForm",
  "workingHours",
  "socialMedia",
] as const
type ContactUsPageSectionKey = (typeof CONTACT_US_PAGE_SECTION_KEYS)[number]
export type { ContactUsPageSectionKey }

function hasAnyMissingStringOrArray(node: unknown): boolean {
  if (typeof node === "string") return node.trim() === ""
  if (Array.isArray(node)) {
    if (node.length === 0) return true
    return node.some((item) => hasAnyMissingStringOrArray(item))
  }
  if (node && typeof node === "object") {
    return Object.values(node as Record<string, unknown>).some((value) => hasAnyMissingStringOrArray(value))
  }
  return false
}

function findFirstMissingPath(node: unknown, path: string[] = []): string | null {
  if (typeof node === "string") {
    return node.trim() === "" ? path.join(".") || "en" : null
  }
  if (Array.isArray(node)) {
    if (node.length === 0) return path.join(".") || "en"
    for (let index = 0; index < node.length; index += 1) {
      const missingPath = findFirstMissingPath(node[index], [...path, `[${index}]`])
      if (missingPath) return missingPath
    }
    return null
  }
  if (node && typeof node === "object") {
    for (const [key, value] of Object.entries(node as Record<string, unknown>)) {
      const missingPath = findFirstMissingPath(value, [...path, key])
      if (missingPath) return missingPath
    }
  }
  return null
}

const quickStatSchema = z.object({
  label: z.string(),
  value: z.string(),
  icon: z.string(),
})

const heroSchema = z.object({
  eyebrow: z.string(),
  title: z.string(),
  description: z.string(),
  imageEyebrow: z.string(),
  image: z.string(),
  imagePublicId: z.string().optional().default(""),
  quickStats: z.array(quickStatSchema),
})

const contactInfoItemSchema = z.object({
  label: z.string(),
  value: z.string(),
  icon: z.string(),
})

const scheduleEntrySchema = z.object({
  day: z.string(),
  hours: z.string(),
})

const socialLinkSchema = z.object({
  platform: z.string(),
  url: z.string(),
})

const formStateSchema = z.object({
  hero: heroSchema,
  contactInfo: z.object({ items: z.array(contactInfoItemSchema) }),
  contactForm: z.object({
    title: z.string(),
    subtitle: z.string(),
    fullNameLabel: z.string(),
    emailAddressLabel: z.string(),
    phoneNumberLabel: z.string(),
    yourMessageLabel: z.string(),
    subjectOptionsTitle: z.string(),
    subjectOptions: z.array(z.string()),
    buttonIcon: z.string(),
    buttonText: z.string(),
    buttonLink: z.string(),
  }),
  workingHours: z.object({
    title: z.string(),
    schedule: z.array(scheduleEntrySchema),
    extraNote: z.string(),
  }),
  socialMedia: z.object({
    title: z.string(),
    socialLinks: z.array(socialLinkSchema),
  }),
})

function strField(o: Record<string, unknown>, key: string, fallback: string): string {
  return typeof o[key] === "string" ? (o[key] as string) : fallback
}

function isQuickStat(x: unknown): x is ContactQuickStat {
  if (!x || typeof x !== "object") return false
  const r = x as { label?: unknown; value?: unknown; icon?: unknown }
  return typeof r.label === "string" && typeof r.value === "string" && typeof r.icon === "string"
}

function isContactInfoItem(x: unknown): x is ContactInfoItem {
  if (!x || typeof x !== "object") return false
  const r = x as { label?: unknown; value?: unknown; icon?: unknown }
  return typeof r.label === "string" && typeof r.value === "string" && typeof r.icon === "string"
}

function isScheduleEntry(x: unknown): x is ScheduleEntry {
  if (!x || typeof x !== "object") return false
  const r = x as { day?: unknown; hours?: unknown }
  return typeof r.day === "string" && typeof r.hours === "string"
}

function isSocialLink(x: unknown): x is SocialLink {
  if (!x || typeof x !== "object") return false
  const r = x as { platform?: unknown; url?: unknown }
  return typeof r.platform === "string" && typeof r.url === "string"
}

export function normalizeContactUsPageFromJson(value: unknown): z.infer<typeof formStateSchema> {
  const base = createEmptyContactUsPageFormState()
  if (value == null || typeof value !== "object" || Array.isArray(value)) return base

  const o = value as Record<string, unknown>
  const heroRaw = o.hero && typeof o.hero === "object" && !Array.isArray(o.hero)
    ? (o.hero as Record<string, unknown>)
    : {}
  const infoRaw = o.contactInfo && typeof o.contactInfo === "object" && !Array.isArray(o.contactInfo)
    ? (o.contactInfo as Record<string, unknown>)
    : {}
  const formRaw = o.contactForm && typeof o.contactForm === "object" && !Array.isArray(o.contactForm)
    ? (o.contactForm as Record<string, unknown>)
    : {}
  const workingRaw = o.workingHours && typeof o.workingHours === "object" && !Array.isArray(o.workingHours)
    ? (o.workingHours as Record<string, unknown>)
    : {}
  const socialRaw = o.socialMedia && typeof o.socialMedia === "object" && !Array.isArray(o.socialMedia)
    ? (o.socialMedia as Record<string, unknown>)
    : {}

  return {
    hero: {
      eyebrow: strField(heroRaw, "eyebrow", base.hero.eyebrow),
      title: strField(heroRaw, "title", base.hero.title),
      description: strField(heroRaw, "description", base.hero.description),
      imageEyebrow: strField(heroRaw, "imageEyebrow", base.hero.imageEyebrow),
      image: strField(heroRaw, "image", base.hero.image),
      imagePublicId: strField(heroRaw, "imagePublicId", base.hero.imagePublicId),
      quickStats: Array.isArray(heroRaw.quickStats)
        ? (heroRaw.quickStats as unknown[]).filter(isQuickStat)
        : base.hero.quickStats,
    },
    contactInfo: {
      items: Array.isArray(infoRaw.items)
        ? (infoRaw.items as unknown[]).filter(isContactInfoItem)
        : base.contactInfo.items,
    },
    contactForm: {
      title: strField(formRaw, "title", base.contactForm.title),
      subtitle: strField(formRaw, "subtitle", base.contactForm.subtitle),
      fullNameLabel: strField(formRaw, "fullNameLabel", base.contactForm.fullNameLabel),
      emailAddressLabel: strField(formRaw, "emailAddressLabel", base.contactForm.emailAddressLabel),
      phoneNumberLabel: strField(formRaw, "phoneNumberLabel", base.contactForm.phoneNumberLabel),
      yourMessageLabel: strField(formRaw, "yourMessageLabel", base.contactForm.yourMessageLabel),
      subjectOptionsTitle: strField(formRaw, "subjectOptionsTitle", base.contactForm.subjectOptionsTitle),
      subjectOptions: Array.isArray(formRaw.subjectOptions)
        ? (formRaw.subjectOptions as unknown[]).filter((item): item is string => typeof item === "string")
        : base.contactForm.subjectOptions,
      buttonIcon: strField(formRaw, "buttonIcon", base.contactForm.buttonIcon),
      buttonText: strField(formRaw, "buttonText", base.contactForm.buttonText),
      buttonLink: strField(formRaw, "buttonLink", base.contactForm.buttonLink),
    },
    workingHours: {
      title: strField(workingRaw, "title", base.workingHours.title),
      schedule: Array.isArray(workingRaw.schedule)
        ? (workingRaw.schedule as unknown[]).filter(isScheduleEntry)
        : base.workingHours.schedule,
      extraNote: strField(workingRaw, "extraNote", base.workingHours.extraNote),
    },
    socialMedia: {
      title: strField(socialRaw, "title", base.socialMedia.title),
      socialLinks: Array.isArray(socialRaw.socialLinks)
        ? (socialRaw.socialLinks as unknown[]).filter(isSocialLink)
        : base.socialMedia.socialLinks,
    },
  }
}

const localesSchema = z.record(z.string(), formStateSchema)

const putBodySchema = z.object({ locales: localesSchema, sectionKey: z.string().optional() })

export function parseContactUsPagePutBody(input: unknown):
  | { ok: true; data: { locales: Record<string, z.infer<typeof formStateSchema>>; sectionKey?: ContactUsPageSectionKey } }
  | { ok: false; error: string } {
  if (!input || typeof input !== "object" || !("locales" in input)) {
    return { ok: false, error: "Invalid body: expected { locales }" }
  }
  const raw = input as { locales: unknown }
  if (!raw.locales || typeof raw.locales !== "object" || Array.isArray(raw.locales)) {
    return { ok: false, error: "Invalid locales" }
  }

  for (const key of Object.keys(raw.locales as Record<string, unknown>)) {
    if (!CONTACT_US_PAGE_LOCALE_CODES.includes(key as ContactUsPageLocaleCode)) {
      return { ok: false, error: `Unknown locale: ${key}` }
    }
  }

  const parsed = putBodySchema.safeParse(input)
  if (!parsed.success) {
    const first = parsed.error.issues[0]
    return { ok: false, error: first?.message ?? "Validation failed" }
  }

  let sectionKey: ContactUsPageSectionKey | undefined
  if (typeof parsed.data.sectionKey === "string") {
    if (!CONTACT_US_PAGE_SECTION_KEYS.includes(parsed.data.sectionKey as ContactUsPageSectionKey)) {
      return { ok: false, error: `Unknown section key: ${parsed.data.sectionKey}` }
    }
    sectionKey = parsed.data.sectionKey as ContactUsPageSectionKey
  }

  const englishLocale = parsed.data.locales.en
  if (!englishLocale) {
    return { ok: false, error: "English (en) content is required" }
  }

  if (sectionKey) {
    const englishSection = englishLocale[sectionKey]
    if (hasAnyMissingStringOrArray(englishSection)) {
      const missingPath = findFirstMissingPath(englishSection, ["en", sectionKey])
      return {
        ok: false,
        error: missingPath
          ? `Please fill all required English fields. Missing: ${missingPath}`
          : "Please fill all required English fields.",
      }
    }
  } else if (hasAnyMissingStringOrArray(englishLocale)) {
    const missingPath = findFirstMissingPath(englishLocale)
    return {
      ok: false,
      error: missingPath
        ? `Please fill all required English fields. Missing: ${missingPath}`
        : "Please fill all required English fields.",
    }
  }

  return { ok: true, data: { locales: parsed.data.locales, sectionKey } }
}

export function parseContactUsPageJsonForStorage(value: unknown): { data: z.infer<typeof formStateSchema> } {
  const data = normalizeContactUsPageFromJson(value)
  const parsed = formStateSchema.safeParse(data)
  return { data: parsed.success ? parsed.data : data }
}
