import { describe, expect, it } from "vitest";
import {
  buildMethodCardWizardInitialValues,
  coreValueDetailsFromWizardFieldBlocks,
  facetDetailsToWizardFieldBlocks,
  overlayFacetPrefillValues,
} from "../../lib/create/methodCardWizardPrefill";
import type { CustomMethodCardFieldBlock } from "../../lib/create/customMethodCardFieldBlocks";

const cardId = "signal";
const blocks: CustomMethodCardFieldBlock[] = [
  { kind: "text", id: "b1", blockTitle: "Notes", placeholderText: "…" },
];

const commHeadings = {
  corePrinciple: "Core Principle & Scope",
  logisticsAdmin: "Logistics, Admin & Norms",
  codeOfConduct: "Code of Conduct",
};

describe("buildMethodCardWizardInitialValues", () => {
  it("uses fallback title and description when meta is missing", () => {
    expect(
      buildMethodCardWizardInitialValues({
        cardId,
        fallbackTitle: "Signal",
        fallbackDescription: "Encrypted messaging.",
        meta: {},
        persistedBlocks: {},
        draftFieldBlocks: null,
      }),
    ).toEqual({
      title: "Signal",
      description: "Encrypted messaging.",
      fieldBlocks: [],
    });
  });

  it("maps facet body fields onto wizard blocks when none exist yet", () => {
    expect(
      buildMethodCardWizardInitialValues({
        cardId,
        fallbackTitle: "Signal",
        fallbackDescription: "Encrypted messaging.",
        meta: {},
        persistedBlocks: {},
        draftFieldBlocks: null,
        facetPrefill: {
          group: "communication",
          draft: {
            corePrinciple: "Privacy first.",
            logisticsAdmin: "Admins steward access.",
            codeOfConduct: "No leaks.",
          },
          headings: commHeadings,
        },
      }).fieldBlocks,
    ).toEqual([
      {
        kind: "text",
        id: "facet-corePrinciple",
        blockTitle: "Core Principle & Scope",
        placeholderText: "Privacy first.",
      },
      {
        kind: "text",
        id: "facet-logisticsAdmin",
        blockTitle: "Logistics, Admin & Norms",
        placeholderText: "Admins steward access.",
      },
      {
        kind: "text",
        id: "facet-codeOfConduct",
        blockTitle: "Code of Conduct",
        placeholderText: "No leaks.",
      },
    ]);
  });

  it("prefers persisted meta title and description over fallbacks", () => {
    expect(
      buildMethodCardWizardInitialValues({
        cardId,
        fallbackTitle: "Signal",
        fallbackDescription: "Encrypted messaging.",
        meta: {
          [cardId]: { label: "Our Signal", supportText: "Private ops." },
        },
        persistedBlocks: { [cardId]: blocks },
        draftFieldBlocks: null,
      }),
    ).toEqual({
      title: "Our Signal",
      description: "Private ops.",
      fieldBlocks: blocks,
    });
  });

  it("overlays current facet field values onto matching persisted blocks", () => {
    const persisted: CustomMethodCardFieldBlock[] = [
      {
        kind: "text",
        id: "facet-corePrinciple",
        blockTitle: "Core Principle & Scope",
        placeholderText: "Stale principle",
      },
      {
        kind: "text",
        id: "extra-notes",
        blockTitle: "Notes",
        placeholderText: "keep",
      },
    ];
    expect(
      buildMethodCardWizardInitialValues({
        cardId,
        fallbackTitle: "Signal",
        fallbackDescription: "Encrypted messaging.",
        meta: {},
        persistedBlocks: { [cardId]: persisted },
        draftFieldBlocks: null,
        facetPrefill: {
          group: "communication",
          draft: {
            corePrinciple: "Updated principle",
            logisticsAdmin: "Updated logistics",
            codeOfConduct: "Updated coc",
          },
          headings: commHeadings,
        },
      }).fieldBlocks,
    ).toEqual([
      {
        kind: "text",
        id: "facet-corePrinciple",
        blockTitle: "Core Principle & Scope",
        placeholderText: "Updated principle",
      },
      {
        kind: "text",
        id: "extra-notes",
        blockTitle: "Notes",
        placeholderText: "keep",
      },
      {
        kind: "text",
        id: "facet-logisticsAdmin",
        blockTitle: "Logistics, Admin & Norms",
        placeholderText: "Updated logistics",
      },
      {
        kind: "text",
        id: "facet-codeOfConduct",
        blockTitle: "Code of Conduct",
        placeholderText: "Updated coc",
      },
    ]);
  });

  it("prefers in-modal field-block drafts over persisted blocks", () => {
    const draft: CustomMethodCardFieldBlock[] = [
      { kind: "proportion", id: "p1", blockTitle: "Share", defaultPercent: 40 },
    ];
    expect(
      buildMethodCardWizardInitialValues({
        cardId,
        fallbackTitle: "Signal",
        fallbackDescription: "Encrypted messaging.",
        meta: {
          [cardId]: { label: "Our Signal", supportText: "Private ops." },
        },
        persistedBlocks: { [cardId]: blocks },
        draftFieldBlocks: draft,
      }).fieldBlocks,
    ).toEqual(draft);
  });
});

describe("facetDetailsToWizardFieldBlocks", () => {
  it("returns no blocks when facet copy is empty", () => {
    expect(
      facetDetailsToWizardFieldBlocks({
        group: "communication",
        draft: {
          corePrinciple: "  ",
          logisticsAdmin: "",
          codeOfConduct: "",
        },
        headings: commHeadings,
      }),
    ).toEqual([]);
  });

  it("maps decision scope chips to a badge block", () => {
    const blocksOut = facetDetailsToWizardFieldBlocks({
      group: "decisionApproaches",
      draft: {
        corePrinciple: "Momentum.",
        applicableScope: ["Daily Operations"],
        selectedApplicableScope: [],
        stepByStepInstructions: "Post a deadline.",
        consensusLevel: 100,
        objectionsDeadlocks: "Any member can block.",
      },
      headings: {
        corePrinciple: "Core Principle",
        applicableScope: "Applicable Scope",
        stepByStepInstructions: "Step-by-Step Instructions",
        consensusLevel: "Consensus Level",
        objectionsDeadlocks: "Objections & Deadlocks",
      },
    });
    expect(blocksOut.find((b) => b.kind === "badges")).toMatchObject({
      kind: "badges",
      blockTitle: "Applicable Scope",
      options: ["Daily Operations"],
    });
    expect(blocksOut.find((b) => b.kind === "proportion")).toMatchObject({
      defaultPercent: 100,
    });
  });

  it("omits a consensus proportion when the draft has no consensus level", () => {
    const blocksOut = facetDetailsToWizardFieldBlocks({
      group: "decisionApproaches",
      draft: {
        corePrinciple: "Momentum.",
        applicableScope: [],
        selectedApplicableScope: [],
        stepByStepInstructions: "Post a deadline.",
        objectionsDeadlocks: "",
      },
      headings: {
        corePrinciple: "Core Principle",
        applicableScope: "Applicable Scope",
        stepByStepInstructions: "Step-by-Step Instructions",
        consensusLevel: "Consensus Level",
        objectionsDeadlocks: "Objections & Deadlocks",
      },
    });
    expect(blocksOut.find((b) => b.kind === "proportion")).toBeUndefined();
  });

  it("does not inject a seeded 75% proportion onto empty custom drafts", () => {
    const next = overlayFacetPrefillValues([], {
      group: "decisionApproaches",
      draft: {
        corePrinciple: "",
        applicableScope: [],
        selectedApplicableScope: [],
        stepByStepInstructions: "",
        consensusLevel: 75,
        objectionsDeadlocks: "",
      },
      headings: {
        corePrinciple: "Core Principle",
        applicableScope: "Applicable Scope",
        stepByStepInstructions: "Step-by-Step Instructions",
        consensusLevel: "Consensus Level",
        objectionsDeadlocks: "Objections & Deadlocks",
      },
    });
    expect(next).toEqual([]);
  });

  it("maps core value meaning and signals onto text blocks", () => {
    expect(
      facetDetailsToWizardFieldBlocks({
        group: "coreValues",
        draft: {
          meaning: "Everyone can join.",
          signals: "Inaccessible venues.",
        },
        headings: {
          meaning: "What does this value mean to your group?",
          signals: "Signals of Violation",
        },
      }),
    ).toEqual([
      {
        kind: "text",
        id: "facet-meaning",
        blockTitle: "What does this value mean to your group?",
        placeholderText: "Everyone can join.",
      },
      {
        kind: "text",
        id: "facet-signals",
        blockTitle: "Signals of Violation",
        placeholderText: "Inaccessible venues.",
      },
    ]);
  });
});

describe("coreValueDetailsFromWizardFieldBlocks", () => {
  it("reads meaning and signals from facet block ids", () => {
    expect(
      coreValueDetailsFromWizardFieldBlocks(
        [
          {
            kind: "text",
            id: "facet-meaning",
            blockTitle: "Meaning",
            placeholderText: "Updated meaning",
          },
          {
            kind: "text",
            id: "facet-signals",
            blockTitle: "Signals",
            placeholderText: "Updated signals",
          },
        ],
        { meaning: "old m", signals: "old s", supportText: "keep" },
      ),
    ).toEqual({
      meaning: "Updated meaning",
      signals: "Updated signals",
      supportText: "keep",
    });
  });
});
