import { describe, expect, it } from "vitest";
import {
  applyDecisionApproachKeyResources,
  decisionApproachKeyResourceCheckboxIds,
  decisionApproachKeyResourceIdsFromLabels,
  decisionApproachScopeForPublish,
  decisionApproachKeyResourceItems,
  decisionApproachKeyResourceLabels,
  selectedKeyResourceLabelsFromCheckedIds,
  stringArraysEqual,
  syncDecisionApproachKeyResourceDetails,
  withDecisionApproachKeyResourceScopes,
} from "../../lib/create/decisionApproachKeyResources";
import type { DecisionApproachDetailEntry } from "../../app/(app)/create/types";

const emptyEntry = (): DecisionApproachDetailEntry => ({
  corePrinciple: "p",
  applicableScope: ["Daily Operations"],
  selectedApplicableScope: [],
  stepByStepInstructions: "s",
  consensusLevel: 75,
  objectionsDeadlocks: "o",
});

describe("decisionApproachKeyResources", () => {
  it("reads the four key-resource items from messages", () => {
    expect(decisionApproachKeyResourceItems()).toEqual([
      { id: "amend", label: "Amend your CommunityRule" },
      { id: "finances", label: "Steward finances" },
      { id: "project", label: "Project level decisions" },
      { id: "discipline", label: "Discipline and member termination" },
    ]);
  });

  it("selects checked key-resource labels without rewriting applicableScope", () => {
    const next = applyDecisionApproachKeyResources(emptyEntry(), [
      "Steward finances",
    ]);
    expect(next.applicableScope).toEqual(["Daily Operations"]);
    expect(next.selectedApplicableScope).toEqual(["Steward finances"]);
  });

  it("keeps non-key chip selections when syncing sidebar checks", () => {
    const next = applyDecisionApproachKeyResources(
      {
        ...emptyEntry(),
        applicableScope: ["Steward finances", "Daily Operations"],
        selectedApplicableScope: ["Daily Operations"],
      },
      ["Steward finances"],
    );
    expect(next.applicableScope).toEqual([
      "Steward finances",
      "Daily Operations",
    ]);
    expect(next.selectedApplicableScope).toEqual([
      "Daily Operations",
      "Steward finances",
    ]);
  });

  it("publishes default scopes plus checked key resources", () => {
    expect(
      decisionApproachScopeForPublish(
        ["Daily Operations", "Minor Expenditures"],
        ["Steward finances"],
      ),
    ).toEqual([
      "Daily Operations",
      "Minor Expenditures",
      "Steward finances",
    ]);
    expect(
      decisionApproachScopeForPublish(
        ["Daily Operations", "Minor Expenditures"],
        ["Daily Operations", "Steward finances"],
      ),
    ).toEqual(["Daily Operations", "Steward finances"]);
    expect(
      decisionApproachScopeForPublish(
        ["Daily Operations", "Minor Expenditures"],
        [],
      ),
    ).toEqual(["Daily Operations", "Minor Expenditures"]);
  });

  it("maps checkbox ids to labels and back", () => {
    expect(selectedKeyResourceLabelsFromCheckedIds(["amend", "project"])).toEqual(
      ["Amend your CommunityRule", "Project level decisions"],
    );
    expect(
      decisionApproachKeyResourceIdsFromLabels([
        "Project level decisions",
        "Unknown",
        "Amend your CommunityRule",
      ]),
    ).toEqual(["amend", "project"]);
  });

  it("derives sidebar checks from the open draft or selected approaches", () => {
    const detailsById = {
      "lazy-consensus": {
        ...emptyEntry(),
        selectedApplicableScope: ["Steward finances"],
      },
      "do-ocracy": {
        ...emptyEntry(),
        selectedApplicableScope: ["Project level decisions"],
      },
    };
    expect(
      decisionApproachKeyResourceCheckboxIds({
        detailsById,
        selectedApproachIds: ["lazy-consensus", "do-ocracy"],
        reminderIds: ["discipline"],
      }),
    ).toEqual(["finances", "project", "discipline"]);
    expect(
      decisionApproachKeyResourceCheckboxIds({
        detailsById,
        selectedApproachIds: ["lazy-consensus", "do-ocracy"],
        reminderIds: ["discipline"],
        openDraft: {
          ...emptyEntry(),
          selectedApplicableScope: ["Amend your CommunityRule"],
        },
      }),
    ).toEqual(["amend"]);
  });

  it("syncs existing and selected approach details", () => {
    const next = syncDecisionApproachKeyResourceDetails(
      { "lazy-consensus": emptyEntry() },
      ["do-ocracy"],
      ["Amend your CommunityRule"],
      (id) => ({
        ...emptyEntry(),
        corePrinciple: id,
        applicableScope: ["Volunteer Tasks"],
      }),
    );
    expect(next["lazy-consensus"]?.selectedApplicableScope).toEqual([
      "Amend your CommunityRule",
    ]);
    expect(next["do-ocracy"]?.corePrinciple).toBe("do-ocracy");
    expect(next["do-ocracy"]?.applicableScope).toEqual(["Volunteer Tasks"]);
    expect(next["do-ocracy"]?.selectedApplicableScope).toEqual([
      "Amend your CommunityRule",
    ]);
  });

  it("compares string arrays by order", () => {
    expect(stringArraysEqual(["a", "b"], ["a", "b"])).toBe(true);
    expect(stringArraysEqual(["a", "b"], ["b", "a"])).toBe(false);
    expect(decisionApproachKeyResourceLabels()).toHaveLength(4);
  });

  it("unions key-resource labels onto an existing scope list", () => {
    expect(
      withDecisionApproachKeyResourceScopes(["Daily Operations"]),
    ).toEqual([
      "Daily Operations",
      "Amend your CommunityRule",
      "Steward finances",
      "Project level decisions",
      "Discipline and member termination",
    ]);
  });
});
