import { getRenderableSectionBlocks } from "@/admin/pages/sectionLayouts";
import type { PageSection } from "@/admin/types";
import { normalizeCourseHeroContent } from "@/components/page-blocks/course-hero/normalizeContent";
import { COURSE_HERO_NAME_PLACEHOLDER } from "@/components/page-blocks/course-hero/defaultContent";
import { resolveBlockSlug } from "@/lib/blockSlug";

/** Supported dynamic placeholders in component content (use as `{subject}`, `{course_name}`, etc.). */
export type ContentPlaceholderKey = "subject" | "course_name" | "grade" | "teacher" | "course";

export type ContentPlaceholderVars = Partial<Record<ContentPlaceholderKey, string>>;

const PLACEHOLDER_PATTERN = /\{(\w+)\}/g;

/** Default text when a placeholder value is missing at render time. */
export const CONTENT_PLACEHOLDER_FALLBACKS: Partial<Record<ContentPlaceholderKey, string>> = {
  subject: "This Subject",
  course_name: "",
  course: "",
  grade: "",
  teacher: "",
};

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

function normalizePlaceholderKey(key: string): ContentPlaceholderKey | null {
  if (key === "course") return "course_name";
  if (key === "subject" || key === "course_name" || key === "grade" || key === "teacher") {
    return key;
  }
  return null;
}

function resolvePlaceholderValue(
  key: string,
  vars: ContentPlaceholderVars,
  fallbacks: Partial<Record<ContentPlaceholderKey, string>>
): string {
  const normalized = normalizePlaceholderKey(key);
  if (!normalized) return "";
  const raw = vars[normalized];
  if (raw != null && raw.trim()) return raw.trim();
  return fallbacks[normalized] ?? "";
}

/**
 * Replace `{subject}`, `{course_name}`, `{grade}`, `{teacher}`, and `{course}` in a string.
 * Replacement runs at render time; stored content keeps the template text.
 */
export function interpolateContentPlaceholders(
  template: string,
  vars: ContentPlaceholderVars,
  fallbacks: Partial<Record<ContentPlaceholderKey, string>> = CONTENT_PLACEHOLDER_FALLBACKS
): string {
  if (!template.includes("{")) return template;
  return template.replace(PLACEHOLDER_PATTERN, (match, key: string) => {
    const normalized = normalizePlaceholderKey(key);
    if (!normalized) return match;
    return resolvePlaceholderValue(key, vars, fallbacks);
  });
}

/** Recursively apply placeholder replacement to strings inside content objects/arrays. */
export function applyContentPlaceholdersDeep<T>(
  value: T,
  vars: ContentPlaceholderVars,
  fallbacks: Partial<Record<ContentPlaceholderKey, string>> = CONTENT_PLACEHOLDER_FALLBACKS
): T {
  if (typeof value === "string") {
    return interpolateContentPlaceholders(value, vars, fallbacks) as T;
  }
  if (Array.isArray(value)) {
    return value.map((item) => applyContentPlaceholdersDeep(item, vars, fallbacks)) as T;
  }
  if (value && typeof value === "object") {
    const out: Record<string, unknown> = {};
    for (const [key, nested] of Object.entries(value as Record<string, unknown>)) {
      out[key] = applyContentPlaceholdersDeep(nested, vars, fallbacks);
    }
    return out as T;
  }
  return value;
}

function firstStringFromBlocks(sections: PageSection[], pick: (content: Record<string, unknown>) => string): string {
  for (const section of sections) {
    for (const block of getRenderableSectionBlocks(section)) {
      const content = (block.content ?? {}) as Record<string, unknown>;
      const value = pick(content).trim();
      if (value) return value;
    }
  }
  return "";
}

function courseHeroContent(sections: PageSection[]): Record<string, unknown> | null {
  for (const section of sections) {
    for (const block of getRenderableSectionBlocks(section)) {
      if (resolveBlockSlug(block) !== "course-hero") continue;
      return (block.content ?? {}) as Record<string, unknown>;
    }
  }
  return null;
}

function parentCourseOverviewFields(sections: PageSection[]): { course: string; gradeBand: string } {
  for (const section of sections) {
    for (const block of getRenderableSectionBlocks(section)) {
      if (resolveBlockSlug(block) !== "parent-course-overview") continue;
      const content = (block.content ?? {}) as Record<string, unknown>;
      const hero = (content.hero ?? {}) as Record<string, unknown>;
      return {
        course: str(hero.course ?? content.course).trim(),
        gradeBand: str(hero.gradeBand ?? content.gradeBand).trim(),
      };
    }
  }
  return { course: "", gradeBand: "" };
}

function gradeFromSections(sections: PageSection[]): string {
  for (const section of sections) {
    for (const block of getRenderableSectionBlocks(section)) {
      const slug = resolveBlockSlug(block);
      const content = (block.content ?? {}) as Record<string, unknown>;
      if (slug === "grade-hero") {
        const title = str(content.title).trim();
        if (title) return title;
      }
      if (slug === "quarter-hero") {
        const subtitle = str(content.subtitle).trim();
        if (subtitle) return subtitle;
      }
    }
  }
  const pco = parentCourseOverviewFields(sections);
  if (pco.gradeBand) return pco.gradeBand;
  return firstStringFromBlocks(sections, (c) => str(c.grade));
}

/** Build placeholder variables from page sections and optional page metadata. */
export function buildContentPlaceholderVars(
  sections: PageSection[],
  extras?: { pageTitle?: string }
): ContentPlaceholderVars {
  const hero = courseHeroContent(sections);
  const pco = parentCourseOverviewFields(sections);

  const rawHeroName = str(hero?.name).trim();
  const heroNameIsTemplate =
    !rawHeroName || rawHeroName === COURSE_HERO_NAME_PLACEHOLDER;
  const courseName =
    (heroNameIsTemplate ? "" : rawHeroName) ||
    pco.course ||
    extras?.pageTitle?.trim() ||
    "";
  // Prefer Course Hero / page title over block-level subject fields (avoids stale "Science" overrides).
  const subject =
    courseName || firstStringFromBlocks(sections, (c) => str(c.subject));
  const grade = gradeFromSections(sections);
  const teacher = firstStringFromBlocks(sections, (c) => str(c.teacher));

  return {
    subject,
    course_name: courseName,
    course: courseName,
    grade,
    teacher,
  };
}

/** Merge block-level fields into page-level placeholder vars (block overrides page). */
export function mergeBlockPlaceholderVars(
  pageVars: ContentPlaceholderVars,
  content: Record<string, unknown>
): ContentPlaceholderVars {
  const merged: ContentPlaceholderVars = { ...pageVars };
  const subject = str(content.subject).trim();
  const courseName = str(content.course_name ?? content.courseName).trim();
  const grade = str(content.grade).trim();
  const teacher = str(content.teacher).trim();

  if (subject) merged.subject = subject;
  if (courseName) {
    merged.course_name = courseName;
    merged.course = courseName;
  }
  if (grade) merged.grade = grade;
  if (teacher) merged.teacher = teacher;

  return merged;
}

export const HOW_CONNECTS_HEADING_TEMPLATE = "How {subject} Connects to All Learning";
export const HOW_CONNECTS_LEGACY_HEADING = "How Science Connects to All Learning";

export const HOW_CONNECTS_LEGACY_BODY =
  "Science provides the CONTENT KNOWLEDGE at the heart of the Project Spine. Every quarter's driving question starts with a scientific phenomenon that connects math, literacy, humanities, and all other subjects.";
export const HOW_CONNECTS_BODY_TEMPLATE =
  "{subject} provides the CONTENT KNOWLEDGE at the heart of the Project Spine. Every quarter's driving question starts with a scientific phenomenon that connects math, literacy, humanities, and all other subjects.";

export const HOW_CONNECTS_LEGACY_THIS_ADDS =
  "Science provides the WHY — the driving questions, investigations, and evidence that give purpose to counting, reading, mapping, and designing.";
export const HOW_CONNECTS_THIS_ADDS_TEMPLATE =
  "{subject} provides the WHY — the driving questions, investigations, and evidence that give purpose to counting, reading, mapping, and designing.";

export const WHY_COURSE_MATTERS_LEGACY_BODY =
  "Science is the foundation of curiosity. Your child will learn to observe carefully, ask meaningful questions, design investigations, and build evidence-based explanations. These skills transfer to every area of life — from solving daily problems to understanding how the world works.";
export const WHY_COURSE_MATTERS_BODY_TEMPLATE =
  "{subject} is the foundation of curiosity. Your child will learn to observe carefully, ask meaningful questions, design investigations, and build evidence-based explanations. These skills transfer to every area of life — from solving daily problems to understanding how the world works.";

/** Legacy library default subject — often copied onto non-Science course pages by mistake. */
export const LEGACY_DEFAULT_SUBJECT = "Science";

function replaceLegacySubjectField(
  content: Record<string, unknown>,
  pageVars: ContentPlaceholderVars
): Record<string, unknown> {
  const blockSubject = str(content.subject).trim();
  const pageCourse = str(pageVars.course_name ?? pageVars.subject).trim();
  if (
    blockSubject === LEGACY_DEFAULT_SUBJECT &&
    pageCourse &&
    pageCourse !== LEGACY_DEFAULT_SUBJECT
  ) {
    const next = { ...content };
    delete next.subject;
    return next;
  }
  return content;
}

function normalizeLegacySubjectString(value: string, legacy: string, template: string): string {
  const trimmed = value.trim();
  if (!trimmed || trimmed === legacy) return template;
  return trimmed;
}

function normalizeHowConnectsContent(
  content: Record<string, unknown>,
  pageVars: ContentPlaceholderVars
): Record<string, unknown> {
  let next = replaceLegacySubjectField(content, pageVars);

  const heading = str(next.heading).trim();
  if (!heading || heading === HOW_CONNECTS_LEGACY_HEADING) {
    next = { ...next, heading: HOW_CONNECTS_HEADING_TEMPLATE };
  }

  const body = str(next.body).trim();
  next = {
    ...next,
    body: normalizeLegacySubjectString(body, HOW_CONNECTS_LEGACY_BODY, HOW_CONNECTS_BODY_TEMPLATE),
  };

  const thisAddsTitle = str(next.thisAddsTitle).trim();
  if (!thisAddsTitle || thisAddsTitle === "What Science Adds") {
    next = { ...next, thisAddsTitle: "What {subject} Adds" };
  }

  const thisAddsText = str(next.thisAddsText).trim();
  next = {
    ...next,
    thisAddsText: normalizeLegacySubjectString(
      thisAddsText,
      HOW_CONNECTS_LEGACY_THIS_ADDS,
      HOW_CONNECTS_THIS_ADDS_TEMPLATE
    ),
  };

  const conn = next.connectionExample;
  if (conn && typeof conn === "object" && !Array.isArray(conn)) {
    const connectionExample = { ...(conn as Record<string, unknown>) };
    const connThisAdds = str(connectionExample.thisAdds).trim();
    if (connThisAdds === HOW_CONNECTS_LEGACY_THIS_ADDS) {
      connectionExample.thisAdds = HOW_CONNECTS_THIS_ADDS_TEMPLATE;
    }
    next = { ...next, connectionExample };
  }

  return next;
}

function normalizeWhyThisCourseMattersContent(content: Record<string, unknown>): Record<string, unknown> {
  const body = str(content.body).trim();
  return {
    ...content,
    body: normalizeLegacySubjectString(body, WHY_COURSE_MATTERS_LEGACY_BODY, WHY_COURSE_MATTERS_BODY_TEMPLATE),
  };
}

/**
 * Resolve block content for preview/live rendering.
 * Applies placeholder replacement without mutating stored editor content.
 */
export function resolveBlockContentForRender(
  content: Record<string, unknown>,
  pageVars: ContentPlaceholderVars,
  options?: { blockSlug?: string }
): Record<string, unknown> {
  let prepared = content;
  if (options?.blockSlug === "how-connects") {
    prepared = normalizeHowConnectsContent(prepared, pageVars);
  }
  if (options?.blockSlug === "why-this-course-matters") {
    prepared = normalizeWhyThisCourseMattersContent(prepared);
  }
  if (options?.blockSlug === "course-hero") {
    prepared = normalizeCourseHeroContent(prepared, pageVars);
  }
  const vars = mergeBlockPlaceholderVars(pageVars, prepared);
  return applyContentPlaceholdersDeep(prepared, vars);
}

/** Vars for single-component previews (component library / picker) from content fields only. */
export function buildContentPlaceholderVarsFromContent(
  content?: Record<string, unknown>
): ContentPlaceholderVars {
  const c = content ?? {};
  const rawName = str(c.course_name ?? c.courseName ?? c.name).trim();
  const nameIsTemplate = !rawName || rawName === COURSE_HERO_NAME_PLACEHOLDER;
  const courseName = nameIsTemplate ? "" : rawName;
  const subject = str(c.subject).trim() || courseName;
  return {
    subject,
    course_name: courseName,
    course: courseName,
    grade: str(c.grade).trim(),
    teacher: str(c.teacher).trim(),
  };
}

export const CONTENT_PLACEHOLDER_HINT =
  "Placeholders: {subject}, {course_name}, {grade}, {teacher} — replaced when the page is rendered.";

/** Apply placeholder resolution for component library / picker previews. */
export function resolvePreviewContent(
  content: Record<string, unknown>,
  options?: { blockSlug?: string }
): Record<string, unknown> {
  const vars = buildContentPlaceholderVarsFromContent(content);
  return resolveBlockContentForRender(content, vars, options);
}
