import { describe, expect, it } from "vitest";
import { parsePublishedDocumentForCommunityRuleDisplay } from "../../lib/create/publishedDocumentToDisplaySections";

describe("parsePublishedDocumentForCommunityRuleDisplay", () => {
  it("returns [] for non-object document", () => {
    expect(parsePublishedDocumentForCommunityRuleDisplay(null)).toEqual([]);
  });

  it("drops Overview and appends Values + methods with value body text", () => {
    const doc = {
      sections: [
        {
          categoryName: "Overview",
          entries: [{ title: "Community", body: "Our river cleanup org." }],
        },
      ],
      coreValues: [
        { chipId: "1", label: "Ecology", meaning: "We protect water.", signals: "Litter = violation." },
      ],
      methodSelections: {
        communication: [
          {
            id: "signal",
            label: "Signal",
            sections: {
              corePrinciple: "Privacy first.",
              logisticsAdmin: "Admins rotate.",
              codeOfConduct: "No doxxing.",
            },
          },
        ],
      },
    };
    const out = parsePublishedDocumentForCommunityRuleDisplay(doc);
    expect(out.map((s) => s.categoryName)).toEqual(["Values", "Communication"]);
    expect(out[0].entries[0].title).toBe("Ecology");
    expect(out[0].entries[0].body).toBe(
      "We protect water.\n\nLitter = violation.",
    );
    expect(out[0].entries[0].blocks).toBeUndefined();
    expect(out[1].entries[0].title).toBe("Signal");
    expect(out[1].entries[0].blocks?.length).toBeGreaterThanOrEqual(3);
  });

  it("strips Overview but keeps other categories when both exist", () => {
    const doc = {
      sections: [
        { categoryName: "Overview", entries: [{ title: "Community", body: "x" }] },
        { categoryName: "Membership", entries: [{ title: "Open", body: "y" }] },
      ],
    };
    const out = parsePublishedDocumentForCommunityRuleDisplay(doc);
    expect(out.map((s) => s.categoryName)).toEqual(["Membership"]);
  });

  it("prefers document.coreValues over a parallel Values section in document.sections", () => {
    const doc = {
      sections: [
        {
          categoryName: "Values",
          entries: [{ title: "From template", body: "Template body" }],
        },
      ],
      coreValues: [
        { label: "Should not duplicate", meaning: "x", signals: "y" },
      ],
    };
    const out = parsePublishedDocumentForCommunityRuleDisplay(doc);
    expect(out.length).toBe(1);
    expect(out[0].categoryName).toBe("Values");
    expect(out[0].entries[0].title).toBe("Should not duplicate");
    expect(out[0].entries[0].body).toBe("x\n\ny");
  });

  it("enriches empty core value copy from presets (label match)", () => {
    const doc = {
      sections: [],
      coreValues: [
        { chipId: "", label: "Interdependence", meaning: "", signals: "" },
      ],
    };
    const out = parsePublishedDocumentForCommunityRuleDisplay(doc);
    expect(out[0].entries[0].body).toMatch(/survival and success/);
  });

  it("replaces template placeholder bodies with preset copy, Values first", () => {
    const placeholder =
      "Suggested focus for this governance area. Replace with your own language in the create flow.";
    const doc = {
      sections: [
        {
          categoryName: "Communication",
          entries: [{ title: "Slack", body: placeholder }],
        },
        {
          categoryName: "Values",
          entries: [{ title: "Adaptability", body: placeholder }],
        },
      ],
    };
    const out = parsePublishedDocumentForCommunityRuleDisplay(doc);
    expect(out.map((s) => s.categoryName)).toEqual(["Values", "Communication"]);
    expect(out[0].entries[0].body).not.toContain("Suggested focus");
    expect(out[0].entries[0].body.length).toBeGreaterThan(20);
    expect(out[1].entries[0].blocks?.length).toBeGreaterThanOrEqual(1);
    expect(out[1].entries[0].blocks?.[0]?.body?.length).toBeGreaterThan(10);
  });

  it("matches parseDocumentSectionsForDisplay when no coreValues or methodSelections", () => {
    const doc = {
      sections: [
        { categoryName: "X", entries: [{ title: "t", body: "b" }] },
      ],
    };
    expect(parsePublishedDocumentForCommunityRuleDisplay(doc)).toEqual(
      doc.sections,
    );
  });

  it("replaces stale document.sections method category with full methodSelections (custom rules)", () => {
    const customId = "b7c0a9f3-0000-4000-8000-000000000001";
    const doc = {
      sections: [
        {
          categoryName: "Communication",
          entries: [
            {
              title: "Slack",
              body: "Only template row; custom card missing from sections.",
            },
          ],
        },
      ],
      methodSelections: {
        communication: [
          {
            id: "slack",
            label: "Slack",
            sections: {
              corePrinciple: "Slack principle",
              logisticsAdmin: "Slack logistics",
              codeOfConduct: "Slack conduct",
            },
          },
          {
            id: customId,
            label: "My custom comms",
            sections: {
              corePrinciple: "Custom principle",
              logisticsAdmin: "",
              codeOfConduct: "",
            },
          },
        ],
      },
    };
    const out = parsePublishedDocumentForCommunityRuleDisplay(doc);
    const comm = out.find((s) => s.categoryName === "Communication");
    expect(comm).toBeDefined();
    expect(comm?.entries.map((e) => e.title)).toEqual([
      "Slack",
      "My custom comms",
    ]);
    expect(
      comm?.entries.some(
        (e) => e.title === "My custom comms" && e.blocks?.length,
      ),
    ).toBe(true);
  });

  it("includes wizard field blocks when methodSelections preset sections are empty (custom UUID)", () => {
    const customId = "b7c0a9f3-0000-4000-8000-000000000001";
    const doc = {
      sections: [
        {
          categoryName: "Communication",
          entries: [{ title: "Stale template row", body: "ignored after merge" }],
        },
      ],
      methodSelections: {
        communication: [
          {
            id: customId,
            label: "Custom method title",
            sections: {
              corePrinciple: "",
              logisticsAdmin: "",
              codeOfConduct: "",
            },
          },
        ],
      },
      customMethodCardFieldBlocksById: {
        [customId]: [
          {
            kind: "text" as const,
            id: "f1",
            blockTitle: "Expectations",
            placeholderText: "Answer stored only on field blocks.",
          },
        ],
      },
    };
    const out = parsePublishedDocumentForCommunityRuleDisplay(doc);
    const comm = out.find((s) => s.categoryName === "Communication");
    expect(comm?.entries.map((e) => e.title)).toEqual(["Custom method title"]);
    expect(comm?.entries[0]?.blocks).toEqual([
      { label: "Expectations", body: "Answer stored only on field blocks." },
    ]);
  });

  it("exposes custom upload image blocks with imageUrl for CommunityRule display", () => {
    const customId = "b7c0a9f3-0000-4000-8000-000000000002";
    const doc = {
      sections: [],
      methodSelections: {
        communication: [
          {
            id: customId,
            label: "Policy with photo",
            sections: {
              corePrinciple: "",
              logisticsAdmin: "",
              codeOfConduct: "",
            },
          },
        ],
      },
      customMethodCardFieldBlocksById: {
        [customId]: [
          {
            kind: "upload" as const,
            id: "u1",
            blockTitle: "Site photo",
            fileName: "garden.jpg",
            assetUrl: "/api/uploads/11111111-1111-4111-8111-111111111111",
          },
        ],
      },
    };
    const out = parsePublishedDocumentForCommunityRuleDisplay(doc);
    const comm = out.find((s) => s.categoryName === "Communication");
    expect(comm?.entries[0]?.blocks).toEqual([
      {
        label: "Site photo",
        body: "",
        imageUrl: "/api/uploads/11111111-1111-4111-8111-111111111111",
      },
    ]);
  });

  it("shows custom decision description without a seeded 75% consensus row", () => {
    const customId = "00000000-0000-4000-8000-000000000170";
    const out = parsePublishedDocumentForCommunityRuleDisplay({
      sections: [],
      methodSelections: {
        decisionApproaches: [
          {
            id: customId,
            label: "Forum proposals",
            supportText: "Anyone can start a thread.",
            sections: {
              corePrinciple: "",
              applicableScope: [],
              selectedApplicableScope: [],
              stepByStepInstructions: "",
              consensusLevel: 75,
              objectionsDeadlocks: "",
            },
          },
        ],
      },
    });
    const decision = out.find((s) => s.categoryName === "Decision-making");
    expect(decision?.entries).toEqual([
      {
        title: "Forum proposals",
        body: "Anyone can start a thread.",
      },
    ]);
  });
});
