import { expect, test } from "bun:test";
import {
  approveTakeover,
  bankerAdjust,
  disconnectPlayer,
  joinSession,
  requestTakeover,
  setBlackout,
  startSession,
  transfer,
} from "./domain";
import { createSession, removeSession } from "./store";

function setupSession() {
  const { session, banker } = createSession("Avery");
  return { session, banker };
}

test("createSession seeds banker with lobby status", () => {
  const { session, banker } = setupSession();
  expect(session.status).toBe("lobby");
  expect(banker.role).toBe("banker");
  expect(session.players.get(banker.id)).toBeDefined();
  expect(session.code.length).toBe(5);
  removeSession(session.id);
});

test("joinSession reuses player when id is provided", () => {
  const { session, banker } = setupSession();
  const player = joinSession(session, "Rosa");
  const rejoin = joinSession(session, "Rosa II", player.id);
  expect(rejoin.id).toBe(player.id);
  expect(rejoin.name).toBe("Rosa II");
  expect(session.players.size).toBe(2);
  removeSession(session.id);
});

test("transfer moves balances between players", () => {
  const { session, banker } = setupSession();
  startSession(session, banker.id);
  const player = joinSession(session, "Sam");
  const other = joinSession(session, "Riley");
  const before = player.balance;
  transfer(session, player.id, other.id, 200, "Rent");
  expect(player.balance).toBe(before - 200);
  removeSession(session.id);
});

test("blackout blocks money movement", () => {
  const { session, banker } = setupSession();
  startSession(session, banker.id);
  const player = joinSession(session, "Kai");
  setBlackout(session, banker.id, true, "City outage");
  const other = joinSession(session, "Pax");
  expect(() => transfer(session, player.id, other.id, 50, "Loan")).toThrow();
  removeSession(session.id);
});

test("blackout does not block banker actions", () => {
  const { session, banker } = setupSession();
  startSession(session, banker.id);
  const player = joinSession(session, "Zuri");
  setBlackout(session, banker.id, true, "City outage");
  expect(() => bankerAdjust(session, banker.id, player.id, 75, "Override")).not.toThrow();
  removeSession(session.id);
});

test("banker can adjust balances", () => {
  const { session, banker } = setupSession();
  startSession(session, banker.id);
  const player = joinSession(session, "Luna");
  bankerAdjust(session, banker.id, player.id, 120, "Bonus");
  expect(player.balance).toBeGreaterThan(1500);
  removeSession(session.id);
});

test("takeover approval assigns dummy to requester", () => {
  const { session, banker } = setupSession();
  startSession(session, banker.id);
  const original = joinSession(session, "Ghost");
  disconnectPlayer(session, original.id);
  const requester = joinSession(session, "Jules");
  requestTakeover(session, requester.id, original.id);
  const assignedId = approveTakeover(session, banker.id, original.id, requester.id);
  expect(assignedId).toBe(original.id);
  expect(session.players.get(original.id)?.isDummy).toBe(false);
  expect(session.players.get(requester.id)).toBeUndefined();
  removeSession(session.id);
});
