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

vi.mock("~/models/simulator", () => ({
  listSportsSeasonSimulatorSummaries: vi.fn(),
}));

vi.mock("~/services/simulations/runner", () => ({
  runSportsSeasonSimulation: vi.fn(),
}));

import { action, loader } from "../admin.simulators";
import { listSportsSeasonSimulatorSummaries } from "~/models/simulator";
import { runSportsSeasonSimulation } from "~/services/simulations/runner";

function postForm(entries: Record<string, string | string[]>) {
  const body = new URLSearchParams();
  for (const [key, value] of Object.entries(entries)) {
    if (Array.isArray(value)) {
      for (const item of value) body.append(key, item);
    } else {
      body.set(key, value);
    }
  }
  return new Request("http://test/admin/simulators", {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: body.toString(),
  });
}

beforeEach(() => {
  vi.clearAllMocks();
});

describe("admin simulators loader", () => {
  it("hides completed seasons", async () => {
    vi.mocked(listSportsSeasonSimulatorSummaries).mockResolvedValue([
      {
        sportsSeasonId: "season-upcoming",
        seasonName: "2026",
        year: 2026,
        seasonStatus: "upcoming",
        simulationStatus: "idle",
        fantasySeasonId: null,
        fantasySeasonName: null,
        leagueName: null,
        sportName: "NBA",
        sportSlug: "nba",
        simulatorType: "nba_bracket",
        simulatorName: "NBA Bracket",
        participantCount: 16,
        participantInputCount: 16,
        lastSimulatedDate: null,
        readiness: {
          status: "ready",
          canRun: true,
          participantInputCount: 16,
          participantCount: 16,
          missingInputs: [],
          warnings: [],
        },
      },
      {
        sportsSeasonId: "season-completed",
        seasonName: "2025",
        year: 2025,
        seasonStatus: "completed",
        simulationStatus: "idle",
        fantasySeasonId: null,
        fantasySeasonName: null,
        leagueName: null,
        sportName: "NFL",
        sportSlug: "nfl",
        simulatorType: "nfl_bracket",
        simulatorName: "NFL Bracket",
        participantCount: 14,
        participantInputCount: 14,
        lastSimulatedDate: "2026-05-11",
        readiness: {
          status: "ready",
          canRun: true,
          participantInputCount: 14,
          participantCount: 14,
          missingInputs: [],
          warnings: [],
        },
      },
    ] as never);

    const response = await loader();

    expect(response).toEqual({
      simulators: [
        expect.objectContaining({
          sportsSeasonId: "season-upcoming",
          seasonStatus: "upcoming",
        }),
      ],
      sports: ["NBA"],
      simulatorTypes: ["nba_bracket"],
    });
  });
});

describe("admin simulators action", () => {
  it("runs one simulator", async () => {
    vi.mocked(runSportsSeasonSimulation).mockResolvedValue({
      sportsSeasonId: "season-1",
      simulatorType: "nba_bracket",
      simulatedParticipants: 30,
      zeroedParticipants: 0,
      snapshotDate: "2026-05-11",
    });

    const response = await action({
      request: postForm({ intent: "run-one", sportsSeasonId: "season-1" }),
      params: {},
      context: {},
    } as never);

    expect(runSportsSeasonSimulation).toHaveBeenCalledWith("season-1");
    expect(response).toEqual({
      success: true,
      message: "Simulation run complete: 1/1 succeeded.",
      results: [{ sportsSeasonId: "season-1", ok: true, message: "Simulated 30 participant(s)." }],
    });
  });

  it("runs selected simulators sequentially and reports failures", async () => {
    vi.mocked(runSportsSeasonSimulation)
      .mockResolvedValueOnce({
        sportsSeasonId: "season-1",
        simulatorType: "nba_bracket",
        simulatedParticipants: 30,
        zeroedParticipants: 0,
        snapshotDate: "2026-05-11",
      })
      .mockRejectedValueOnce(new Error("Simulator is not ready: source odds."));

    const response = await action({
      request: postForm({ intent: "run-selected", sportsSeasonId: ["season-1", "season-2"] }),
      params: {},
      context: {},
    } as never);

    expect(runSportsSeasonSimulation).toHaveBeenNthCalledWith(1, "season-1");
    expect(runSportsSeasonSimulation).toHaveBeenNthCalledWith(2, "season-2");
    expect(response).toEqual({
      success: false,
      message: "Simulation run complete: 1/2 succeeded.",
      results: [
        { sportsSeasonId: "season-1", ok: true, message: "Simulated 30 participant(s)." },
        { sportsSeasonId: "season-2", ok: false, message: "Simulator is not ready: source odds." },
      ],
    });
  });
});
