import { render, screen, fireEvent } from "@testing-library/react";
import SimpleProgram from "../../../src/pages/SimpleProgram/SimpleProgram";
import useProgramStore from "../../../src/utils/programStore";

/**
 * Helper to preload the program store before rendering.
 */
function loadProgram(phases: Record<string, unknown>[]) {
  useProgramStore.getState().setProgramState({ phases });
}

describe("SimpleProgram", () => {
  beforeEach(() => {
    loadProgram([]);
  });

  test("shows empty state when no program is loaded", () => {
    render(<SimpleProgram />);
    expect(screen.getByText("No program loaded.")).toBeInTheDocument();
  });

  test("renders first phase content", () => {
    loadProgram([
      {
        id: "phase-1",
        norms: [{ id: "n1", norm: "Be polite" }],
        goals: [{ id: "g1", description: "Finish task", achieved: true }],
        triggers: [{ id: "t1", label: "Keyword trigger" }],
      },
    ]);

    render(<SimpleProgram />);

    expect(screen.getByText("Phase 1 / 1")).toBeInTheDocument();
    expect(screen.getByText("Be polite")).toBeInTheDocument();
    expect(screen.getByText("Finish task")).toBeInTheDocument();
    expect(screen.getByText("Keyword trigger")).toBeInTheDocument();
  });

  test("renders empty messages when phase has no data", () => {
    loadProgram([
      {
        id: "phase-1",
        norms: [],
        goals: [],
        triggers: [],
      },
    ]);

    render(<SimpleProgram />);

    expect(screen.getAllByText("No norms defined.").length).toBeGreaterThanOrEqual(1);
    expect(screen.getAllByText("No goals defined.").length).toBeGreaterThanOrEqual(1);
    expect(screen.getAllByText("No triggers defined.").length).toBeGreaterThanOrEqual(1);
    expect(
      screen.getByText("No conditional norms defined.")
    ).toBeInTheDocument();
  });

  test("allows navigating between phases", () => {
    loadProgram([
      {
        id: "phase-1",
        norms: [],
        goals: [],
        triggers: [],
      },
      {
        id: "phase-2",
        norms: [{ id: "n2", norm: "Be careful" }],
        goals: [],
        triggers: [],
      },
    ]);

    render(<SimpleProgram />);

    expect(screen.getByText("Phase 1 / 2")).toBeInTheDocument();

    fireEvent.click(screen.getByText("Next ▶"));

    expect(screen.getByText("Phase 2 / 2")).toBeInTheDocument();
    expect(screen.getByText("Be careful")).toBeInTheDocument();
  });

  test("prev button is disabled on first phase", () => {
    loadProgram([{ id: "phase-1", norms: [], goals: [], triggers: [] }]);

    render(<SimpleProgram />);
    expect(screen.getByText("◀ Prev")).toBeDisabled();
  });

  test("next button is disabled on last phase", () => {
    loadProgram([{ id: "phase-1", norms: [], goals: [], triggers: [] }]);

    render(<SimpleProgram />);
    expect(screen.getByText("Next ▶")).toBeDisabled();
  });

  test("prev and next buttons enable/disable correctly when navigating", () => {
    loadProgram([
      { id: "p1", norms: [], goals: [], triggers: [] },
      { id: "p2", norms: [], goals: [], triggers: [] },
    ]);

    render(<SimpleProgram />);

    const prev = screen.getByText("◀ Prev");
    const next = screen.getByText("Next ▶");

    expect(prev).toBeDisabled();
    expect(next).not.toBeDisabled();

    fireEvent.click(next);

    expect(prev).not.toBeDisabled();
    expect(next).toBeDisabled();
  });

  test("renders achieved and unachieved goals with correct icons", () => {
    loadProgram([
      {
        id: "phase-1",
        norms: [],
        goals: [
          { id: "g1", description: "Done goal", achieved: true },
          { id: "g2", description: "Failed goal", achieved: false },
        ],
        triggers: [],
      },
    ]);

    render(<SimpleProgram />);

    expect(screen.getByText("✔")).toBeInTheDocument();
    expect(screen.getByText("✖")).toBeInTheDocument();
    expect(screen.getByText("Done goal")).toBeInTheDocument();
    expect(screen.getByText("Failed goal")).toBeInTheDocument();
  });

  test("renders fallback labels when optional fields are missing", () => {
    loadProgram([
      {
        id: "phase-1",
        norms: [{}],
        goals: [{}],
        triggers: [{}],
      },
    ]);

    render(<SimpleProgram />);

    expect(screen.getByText("Unnamed norm")).toBeInTheDocument();
    expect(screen.getByText("Unnamed goal")).toBeInTheDocument();
    expect(screen.getByText("Unnamed trigger")).toBeInTheDocument();
  });

  test("does not crash when navigating beyond boundaries", () => {
    loadProgram([
      { id: "p1", norms: [], goals: [], triggers: [] },
      { id: "p2", norms: [], goals: [], triggers: [] },
    ]);

    render(<SimpleProgram />);

    fireEvent.click(screen.getByText("Next ▶"));
    fireEvent.click(screen.getByText("Next ▶"));

    expect(screen.getByText("Phase 2 / 2")).toBeInTheDocument();

    fireEvent.click(screen.getByText("◀ Prev"));
    fireEvent.click(screen.getByText("◀ Prev"));

    expect(screen.getByText("Phase 1 / 2")).toBeInTheDocument();
  });
});
