import type { Session } from "./types";
import type { Player, SessionSnapshot } from "../shared/types";
import { createId, createSessionCode, now, DEFAULT_START_BALANCE } from "./util";
import { clearPushTokensForSession } from "./notifications";

const sessions = new Map<string, Session>();
const sessionsByCode = new Map<string, string>();

export const TEST_SESSION_CODE = "TEST";
const TEST_BANKER_NAME = "Alan Wa Chahabab";
const TEST_PLAYER_NAMES = ["Nesta", "Niko Stinko", "Gaspard l'Batard"];

export type CreateSessionResult = {
  session: Session;
  banker: Player;
};

export function createSession(bankerName: string): CreateSessionResult {
  const id = createId();
  const code = createSessionCode(new Set(sessionsByCode.keys()));
  const createdAt = now();
  const bankerId = createId();

  const banker: Player = {
    id: bankerId,
    name: bankerName.trim() || "Banker",
    role: "banker",
    balance: 0,
    connected: true,
    isDummy: false,
    joinedAt: createdAt,
    lastActiveAt: createdAt,
  };

  const session: Session = {
    id,
    code,
    status: "lobby",
    createdAt,
    bankerId,
    blackoutActive: false,
    blackoutReason: null,
    players: new Map([[bankerId, banker]]),
    transactions: [],
    chats: [],
    groups: [],
    takeoverRequests: [],
  };

  sessions.set(id, session);
  sessionsByCode.set(code, id);

  return { session, banker };
}

export function isTestSessionCode(code: string): boolean {
  return code.trim().toUpperCase() === TEST_SESSION_CODE;
}

export function createTestSession(): Session {
  const id = createId();
  const createdAt = now();
  const bankerId = createId();

  const banker: Player = {
    id: bankerId,
    name: TEST_BANKER_NAME,
    role: "banker",
    balance: 0,
    connected: true,
    isDummy: false,
    joinedAt: createdAt,
    lastActiveAt: createdAt,
  };

  const players = new Map<string, Player>();
  players.set(bankerId, banker);
  TEST_PLAYER_NAMES.forEach((name) => {
    const playerId = createId();
    players.set(playerId, {
      id: playerId,
      name,
      role: "player",
      balance: DEFAULT_START_BALANCE,
      connected: true,
      isDummy: false,
      joinedAt: createdAt,
      lastActiveAt: createdAt,
    });
  });

  const session: Session = {
    id,
    code: TEST_SESSION_CODE,
    status: "active",
    createdAt,
    bankerId,
    blackoutActive: false,
    blackoutReason: null,
    players,
    transactions: [],
    chats: [],
    groups: [],
    takeoverRequests: [],
    isTest: true,
  };

  sessions.set(id, session);

  return session;
}

export function createTestPreview(): SessionSnapshot {
  const createdAt = now();
  const bankerId = createId();
  const players: Player[] = [
    {
      id: bankerId,
      name: TEST_BANKER_NAME,
      role: "banker",
      balance: 0,
      connected: true,
      isDummy: false,
      joinedAt: createdAt,
      lastActiveAt: createdAt,
    },
    ...TEST_PLAYER_NAMES.map((name) => ({
      id: createId(),
      name,
      role: "player" as const,
      balance: DEFAULT_START_BALANCE,
      connected: true,
      isDummy: false,
      joinedAt: createdAt,
      lastActiveAt: createdAt,
    })),
  ];

  return {
    id: TEST_SESSION_CODE,
    code: TEST_SESSION_CODE,
    status: "active",
    createdAt,
    bankerId,
    blackoutActive: false,
    blackoutReason: null,
    players,
    transactions: [],
    chats: [],
    groups: [],
    takeoverRequests: [],
  };
}

export function getSession(id: string): Session | null {
  return sessions.get(id) ?? null;
}

export function getSessionByCode(code: string): Session | null {
  const id = sessionsByCode.get(code.toUpperCase());
  if (!id) {
    return null;
  }
  return sessions.get(id) ?? null;
}

export function removeSession(id: string): void {
  const session = sessions.get(id);
  if (!session) {
    return;
  }
  sessions.delete(id);
  sessionsByCode.delete(session.code);
  clearPushTokensForSession(id);
}

export function listSessions(): Session[] {
  return Array.from(sessions.values());
}
