import type {
  CommunityStructureChipSnapshotRow,
  CreateFlowState,
} from "../../app/(app)/create/types";
import coreValuesMessages from "../../messages/en/create/customRule/coreValues.json";
import { assignTemplateMethodSlugsToPrefill } from "./customRuleFacets";
import { methodSlugFromTitle } from "./methodSlugFromTitle";

type TemplateEntry = { title: unknown };
type TemplateSection = { categoryName: unknown; entries: unknown };

function isTemplateSection(x: unknown): x is TemplateSection {
  if (!x || typeof x !== "object") return false;
  const o = x as Record<string, unknown>;
  return typeof o.categoryName === "string" && Array.isArray(o.entries);
}

function entryTitles(entries: unknown): string[] {
  if (!Array.isArray(entries)) return [];
  const out: string[] = [];
  for (const raw of entries) {
    if (!raw || typeof raw !== "object") continue;
    const title = (raw as TemplateEntry).title;
    if (typeof title !== "string") continue;
    const trimmed = title.trim();
    if (trimmed.length > 0) out.push(trimmed);
  }
  return out;
}

/** Normalise a Figma template category header ("Decision-making") for matching. */
function normaliseCategoryKey(name: string): string {
  return name.toLowerCase().replace(/[^a-z]+/g, "");
}

/** Preset core-value labels with the chip id (1-based preset index as string) the select screen expects. */
type CorePresetRow = { id: string; label: string };
const CORE_VALUE_PRESETS: readonly CorePresetRow[] = (() => {
  const raw = (coreValuesMessages as { values: unknown }).values;
  if (!Array.isArray(raw)) return [];
  return raw.map((v, i) => ({
    id: String(i + 1),
    label: typeof v === "string" ? v : (v as { label: string }).label,
  }));
})();

function buildCoreValuePrefill(
  titles: readonly string[],
): Pick<CreateFlowState, "selectedCoreValueIds" | "coreValuesChipsSnapshot"> {
  const wantedByLower = new Map<string, string>();
  for (const t of titles) wantedByLower.set(t.toLowerCase(), t);

  const selected: string[] = [];
  const snapshot: CommunityStructureChipSnapshotRow[] = [];

  for (const preset of CORE_VALUE_PRESETS) {
    const isSelected = wantedByLower.delete(preset.label.toLowerCase());
    snapshot.push({
      id: preset.id,
      label: preset.label,
      state: isSelected ? "selected" : "unselected",
    });
    if (isSelected) selected.push(preset.id);
  }

  // Any template labels not matching a preset ride along as custom chip rows
  // so templates authored with bespoke values still pre-select on the screen.
  for (const original of wantedByLower.values()) {
    const id = `template-cv-${methodSlugFromTitle(original) || snapshot.length}`;
    snapshot.push({ id, label: original, state: "selected" });
    selected.push(id);
  }

  return {
    selectedCoreValueIds: selected,
    coreValuesChipsSnapshot: snapshot,
  };
}

/**
 * Map a curated template `body` (DB shape — `sections[]` with `categoryName`
 * + `entries[].title`) to the `CreateFlowState` keys the Create Custom Rule
 * screens read for pre-selection. Used by the "Customize" handler on
 * `/create/review-template/[slug]` so clicking Customize drops the user into
 * the custom-rule flow with the template's chips already highlighted.
 *
 * Produces:
 * - `selectedCoreValueIds` + `coreValuesChipsSnapshot` — preset match by
 *   label; non-matching titles become custom chip rows so bespoke template
 *   values still appear selected.
 * - `selectedCommunicationMethodIds`, `selectedMembershipMethodIds`,
 *   `selectedDecisionApproachIds`, `selectedConflictManagementIds` — chip
 *   ids derived via {@link methodSlugFromTitle}, matching the `methods[].id`
 *   produced by the one-time messages ingest.
 *
 * Returns an empty object for malformed bodies (no sections array).
 */
export function buildTemplateCustomizePrefill(
  body: unknown,
): Partial<CreateFlowState> {
  if (!body || typeof body !== "object") return {};
  const sections = (body as { sections?: unknown }).sections;
  if (!Array.isArray(sections)) return {};

  const prefill: Partial<CreateFlowState> = {};

  for (const raw of sections) {
    if (!isTemplateSection(raw)) continue;
    const key = normaliseCategoryKey(raw.categoryName as string);
    const titles = entryTitles(raw.entries);
    if (titles.length === 0) continue;

    if (key === "values" || key === "corevalues") {
      Object.assign(prefill, buildCoreValuePrefill(titles));
      continue;
    }

    const slugs = titles.map(methodSlugFromTitle).filter((s) => s.length > 0);
    if (slugs.length === 0) continue;

    assignTemplateMethodSlugsToPrefill(prefill, key, slugs);
  }

  return prefill;
}

/**
 * Values section only — delegates to {@link buildTemplateCustomizePrefill}
 * (same matching rules as Customize). Used by tests and any caller that
 * needs core-value snapshot seeding without method fields.
 */
export function buildCoreValuesPrefillFromTemplateBody(
  body: unknown,
): Partial<CreateFlowState> {
  const full = buildTemplateCustomizePrefill(body);
  if (full.selectedCoreValueIds === undefined) return {};
  return {
    selectedCoreValueIds: full.selectedCoreValueIds,
    coreValuesChipsSnapshot: full.coreValuesChipsSnapshot,
  };
}
