import { buildDefaultHeroTabs } from "./buildDefaultHeroTabs";
import {
  defaultHeroContent,
  defaultHeroFieldLabels,
  type HeroContent,
  type HeroTab,
  type HeroTabCourse,
  type HeroTabCourseGroup,
  type HeroTabTrait,
  type HeroTabTraitGroup,
} from "./defaultContent";

function isPlainObject(value: unknown): value is Record<string, unknown> {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}

function str(value: unknown, fallback: string): string {
  return typeof value === "string" ? value : fallback;
}

function num(value: unknown, fallback: number): number {
  return typeof value === "number" && Number.isFinite(value) ? value : fallback;
}

function normalizeTrait(raw: unknown, fallback: HeroTabTrait): HeroTabTrait {
  const o = isPlainObject(raw) ? raw : {};
  return {
    trait: str(o.trait, fallback.trait),
    pct: num(o.pct, fallback.pct),
  };
}

function normalizeTraitGroup(raw: unknown, fallback: HeroTabTraitGroup): HeroTabTraitGroup {
  const o = isPlainObject(raw) ? raw : {};
  const traitsRaw = Array.isArray(o.traits) ? o.traits : fallback.traits;
  return {
    mindset: str(o.mindset, fallback.mindset),
    traits: traitsRaw.map((item, index) => normalizeTrait(item, fallback.traits[index] ?? { trait: "", pct: 0 })),
  };
}

function normalizeCourse(raw: unknown, fallback: HeroTabCourse): HeroTabCourse {
  const o = isPlainObject(raw) ? raw : {};
  const slug = str(o.slug, fallback.slug);
  const href = str(o.href, fallback.href || (slug ? `/course/${slug}` : ""));
  return {
    name: str(o.name, fallback.name),
    emoji: str(o.emoji, fallback.emoji),
    slug,
    href,
    pct: num(o.pct, fallback.pct),
  };
}

function normalizeCourseGroup(raw: unknown, fallback: HeroTabCourseGroup): HeroTabCourseGroup {
  const o = isPlainObject(raw) ? raw : {};
  const coursesRaw = Array.isArray(o.courses) ? o.courses : fallback.courses;
  return {
    category: str(o.category, fallback.category),
    courses: coursesRaw.map((item, index) =>
      normalizeCourse(item, fallback.courses[index] ?? { name: "", emoji: "", slug: "", href: "", pct: 0 })
    ),
  };
}

function findDefaultTab(key: string, index: number): HeroTab {
  const defaults = buildDefaultHeroTabs();
  return defaults.find((tab) => tab.key === key) ?? defaults[index] ?? defaults[0];
}

function normalizeTab(raw: unknown, index: number): HeroTab {
  const fallback = findDefaultTab(
    isPlainObject(raw) ? str(raw.key, `tab-${index}`) : `tab-${index}`,
    index
  );
  const o = isPlainObject(raw) ? raw : {};
  const positionIn = isPlainObject(o.position) ? o.position : {};

  const traitGroupsRaw = Array.isArray(o.traitGroups) ? o.traitGroups : null;
  const courseGroupsRaw = Array.isArray(o.courseGroups) ? o.courseGroups : null;

  const traitGroups =
    traitGroupsRaw && traitGroupsRaw.length > 0
      ? traitGroupsRaw.map((item, groupIndex) =>
          normalizeTraitGroup(item, fallback.traitGroups[groupIndex] ?? { mindset: "", traits: [] })
        )
      : fallback.traitGroups.map((group) => ({
          mindset: group.mindset,
          traits: group.traits.map((trait) => ({ ...trait })),
        }));

  const courseGroups =
    courseGroupsRaw && courseGroupsRaw.length > 0
      ? courseGroupsRaw.map((item, groupIndex) =>
          normalizeCourseGroup(item, fallback.courseGroups[groupIndex] ?? { category: "", courses: [] })
        )
      : fallback.courseGroups.map((group) => ({
          category: group.category,
          courses: group.courses.map((course) => ({ ...course })),
        }));

  return {
    key: str(o.key, fallback.key),
    title: str(o.title, fallback.title),
    emoji: str(o.emoji, fallback.emoji),
    color: str(o.color, fallback.color),
    desc: str(o.desc, fallback.desc),
    buttonLabel: str(o.buttonLabel, fallback.buttonLabel),
    iconSrc: str(o.iconSrc, fallback.iconSrc),
    position: {
      desktop: str(positionIn.desktop, fallback.position.desktop),
      mobileOrder: num(positionIn.mobileOrder, fallback.position.mobileOrder),
    },
    traitGroups,
    courseGroups,
  };
}

function readRawTabs(input: Record<string, unknown>): unknown[] | null {
  if (Array.isArray(input.tabs)) return input.tabs;
  if (Array.isArray(input.dimensions)) return input.dimensions;
  return null;
}

/** Merge partial hero content with defaults so paste/edit always has the full structure. */
export function normalizeHeroContent(content: Record<string, unknown> | null | undefined): HeroContent {
  const input = content ?? {};
  const logoIn = isPlainObject(input.logo) ? input.logo : {};
  const horseIn = isPlainObject(input.horseImage) ? input.horseImage : {};
  const panelIn = isPlainObject(input.detailPanel) ? input.detailPanel : {};
  const labelsIn = isPlainObject(input.__fieldLabels) ? input.__fieldLabels : {};

  const rawTabs = readRawTabs(input);
  const tabs =
    rawTabs && rawTabs.length > 0
      ? rawTabs.map((item, index) => normalizeTab(item, index))
      : buildDefaultHeroTabs();

  const fieldLabels = {
    ...defaultHeroFieldLabels,
    ...Object.fromEntries(
      Object.entries(labelsIn).filter((entry): entry is [string, string] => typeof entry[1] === "string")
    ),
  };

  return {
    __required: Array.isArray(input.__required)
      ? input.__required.filter((x): x is string => typeof x === "string")
      : defaultHeroContent.__required,
    __fieldLabels: fieldLabels,
    logo: {
      src: str(logoIn.src, defaultHeroContent.logo.src),
      alt: str(logoIn.alt, defaultHeroContent.logo.alt),
    },
    title: str(input.title, defaultHeroContent.title),
    subtitle: str(input.subtitle, defaultHeroContent.subtitle),
    horseImage: {
      src: str(horseIn.src, defaultHeroContent.horseImage.src),
      alt: str(horseIn.alt, defaultHeroContent.horseImage.alt),
    },
    tabs,
    detailPanel: {
      traitsSectionTitle: str(panelIn.traitsSectionTitle, defaultHeroContent.detailPanel.traitsSectionTitle),
      coursesSectionTitle: str(panelIn.coursesSectionTitle, defaultHeroContent.detailPanel.coursesSectionTitle),
      emptyCoursesMessage: str(panelIn.emptyCoursesMessage, defaultHeroContent.detailPanel.emptyCoursesMessage),
    },
  };
}
