import { describe, expect, it } from "vitest";

import { validatePlannerResult } from "./planner.js";

function basePlan(overrides: Record<string, unknown> = {}) {
  return {
    pageUpdates: [],
    newPages: [],
    unresolvedMentions: [],
    promotions: [],
    ...overrides,
  };
}

describe("validatePlannerResult", () => {
  it("treats blank optional ontology strings as absent", () => {
    const plan = basePlan({
      newPages: [
        {
          type: "topic",
          title: "Pricing Notes",
          slug: "pricing-notes",
          entityTypeSlug: " ",
          sections: [
            {
              slug: "summary",
              heading: "Summary",
              body_md: "Pricing was discussed.",
              facetSlug: "",
            },
          ],
        },
      ],
    });

    expect(() => validatePlannerResult(plan)).not.toThrow();
    expect(
      (plan.newPages as Array<Record<string, unknown>>)[0],
    ).not.toHaveProperty("entityTypeSlug");
    expect(
      (plan.newPages as Array<{ sections: Array<Record<string, unknown>> }>)[0]
        .sections[0],
    ).not.toHaveProperty("facetSlug");
  });

  it("still rejects non-string optional ontology fields", () => {
    const plan = basePlan({
      newPages: [
        {
          type: "topic",
          title: "Pricing Notes",
          slug: "pricing-notes",
          entityTypeSlug: 7,
          sections: [],
        },
      ],
    });

    expect(() => validatePlannerResult(plan)).toThrow(
      "newPages.entityTypeSlug must be a non-empty string when present",
    );
  });

  it("normalizes ontology entity slugs that arrive in the page type field", () => {
    const plan = basePlan({
      newPages: [
        {
          type: "opportunity",
          title: "Pipeline Notes",
          slug: "pipeline-notes",
          sections: [],
        },
      ],
    });

    expect(() => validatePlannerResult(plan)).not.toThrow();
    expect((plan.newPages as Array<Record<string, unknown>>)[0]).toMatchObject({
      type: "entity",
      entityTypeSlug: "opportunity",
    });
  });

  it("normalizes approved activity ontology slugs from the page type field", () => {
    const plan = basePlan({
      newPages: [
        {
          type: "activity",
          title: "Cooking Class",
          slug: "cooking-class",
          sections: [],
        },
      ],
    });

    expect(() => validatePlannerResult(plan)).not.toThrow();
    expect((plan.newPages as Array<Record<string, unknown>>)[0]).toMatchObject({
      type: "entity",
      entityTypeSlug: "activity",
    });
  });

  it("normalizes ontology entity slugs on promoted mentions", () => {
    const plan = basePlan({
      promotions: [
        {
          mentionId: "mention-1",
          reason: "Repeated trip evidence.",
          type: "place",
          title: "Florence",
          slug: "florence",
          sections: [],
        },
      ],
    });

    expect(() => validatePlannerResult(plan)).not.toThrow();
    expect((plan.promotions as Array<Record<string, unknown>>)[0]).toMatchObject({
      type: "entity",
      entityTypeSlug: "place",
    });
  });

  it("drops malformed promotions instead of failing the whole plan", () => {
    const plan = basePlan({
      promotions: [
        {
          reason: "The model emitted a title but no unresolved mention id.",
          type: "place",
          title: "Florence",
          slug: "florence",
          sections: [],
        },
        {
          mentionId: "mention-1",
          reason: "Repeated trip evidence.",
          type: "place",
          title: "Florence",
          slug: "florence",
          sections: [
            null,
            {
              slug: "overview",
              heading: "Overview",
              body_md: "Florence appears repeatedly.",
            },
          ],
        },
      ],
    });

    expect(() => validatePlannerResult(plan)).not.toThrow();
    expect(plan.promotions).toHaveLength(1);
    expect((plan.promotions as Array<Record<string, unknown>>)[0]).toMatchObject({
      mentionId: "mention-1",
      type: "entity",
      entityTypeSlug: "place",
      sections: [
        {
          slug: "overview",
          heading: "Overview",
          body_md: "Florence appears repeatedly.",
        },
      ],
    });
  });

  it("drops page update facet slugs when the entity type is missing", () => {
    const plan = basePlan({
      pageUpdates: [
        {
          pageId: "page-1",
          sections: [
            {
              slug: "summary",
              rationale: "Fresh evidence.",
              proposed_body_md: "The opportunity was discussed.",
              facetSlug: "overview",
              source_refs: ["mem-1"],
            },
          ],
        },
      ],
    });

    expect(() => validatePlannerResult(plan)).not.toThrow();
    expect(
      (
        plan.pageUpdates as Array<{
          sections: Array<Record<string, unknown>>;
        }>
      )[0].sections[0],
    ).not.toHaveProperty("facetSlug");
  });

  it("drops new page facet slugs when the entity type is missing", () => {
    const plan = basePlan({
      newPages: [
        {
          type: "entity",
          title: "Pricing Notes",
          slug: "pricing-notes",
          sections: [
            {
              slug: "summary",
              heading: "Summary",
              body_md: "Pricing was discussed.",
              facetSlug: "overview",
              source_refs: ["mem-1"],
            },
          ],
          source_refs: ["mem-1"],
        },
      ],
    });

    expect(() => validatePlannerResult(plan)).not.toThrow();
    expect(
      (
        plan.newPages as Array<{
          sections: Array<Record<string, unknown>>;
        }>
      )[0].sections[0],
    ).not.toHaveProperty("facetSlug");
  });
});
