import { create } from "zustand";
import { GameSession, Player, Round, RoundScore } from "../types";
import { db } from "../database/db";
import { generateId } from "../utils/id";

interface GameState {
  activeSession: GameSession | null;
  setActiveSession: (session: GameSession | null) => void;
  loadSession: (sessionId: string) => Promise<void>;
  saveSession: () => Promise<void>;

  // Game Actions
  startNewGame: (
    gameId: string,
    players: Player[],
    options: Record<string, any>,
    profileId: string,
    locationId?: string,
  ) => Promise<string>;
  addRound: (scores: RoundScore[]) => Promise<void>;
  updateRound: (roundId: string, scores: RoundScore[]) => Promise<void>;
  removeRound: (roundId: string) => Promise<void>;
  undoLastRound: () => Promise<void>;
  finishGame: (winnerIds: string[]) => Promise<void>;
}

export const useGameStore = create<GameState>((set, get) => ({
  activeSession: null,

  setActiveSession: (session) => set({ activeSession: session }),

  loadSession: async (sessionId: string) => {
    const session = await db.sessions.get(sessionId);
    if (session) {
      set({ activeSession: session });
    }
  },

  saveSession: async () => {
    const { activeSession } = get();
    if (activeSession) {
      await db.sessions.put({ ...activeSession, updatedAt: Date.now() });
    }
  },

  startNewGame: async (gameId, players, options, profileId, locationId) => {
    const now = Date.now();
    const newSession: GameSession = {
      id: generateId(),
      gameId,
      dateStart: now,
      players,
      rounds: [],
      status: "playing",
      options,
      locationId,
      profileId,
      updatedAt: now,
    };

    await db.sessions.add(newSession);
    set({ activeSession: newSession });
    return newSession.id;
  },

  addRound: async (scores) => {
    const { activeSession, saveSession } = get();
    if (!activeSession) return;

    const newRound: Round = {
      id: generateId(),
      roundNumber: activeSession.rounds.length + 1,
      scores,
    };

    set({
      activeSession: {
        ...activeSession,
        rounds: [...activeSession.rounds, newRound],
      },
    });

    await saveSession();
  },

  updateRound: async (roundId, scores) => {
    const { activeSession, saveSession } = get();
    if (!activeSession) return;

    const updatedRounds = activeSession.rounds.map((r) =>
      r.id === roundId ? { ...r, scores } : r,
    );

    set({
      activeSession: {
        ...activeSession,
        rounds: updatedRounds,
      },
    });

    await saveSession();
  },

  removeRound: async (roundId) => {
    const { activeSession, saveSession } = get();
    if (!activeSession) return;

    const updatedRounds = activeSession.rounds
      .filter((r) => r.id !== roundId)
      .map((r, index) => ({
        ...r,
        roundNumber: index + 1,
      }));

    set({
      activeSession: {
        ...activeSession,
        rounds: updatedRounds,
      },
    });

    await saveSession();
  },

  undoLastRound: async () => {
    const { activeSession, saveSession } = get();
    if (!activeSession || activeSession.rounds.length === 0) return;

    const updatedRounds = activeSession.rounds.slice(0, -1);

    set({
      activeSession: {
        ...activeSession,
        rounds: updatedRounds,
      },
    });

    await saveSession();
  },

  finishGame: async (winnerIds) => {
    const { activeSession, saveSession } = get();
    if (!activeSession) return;

    set({
      activeSession: {
        ...activeSession,
        status: "finished",
        dateEnd: Date.now(),
        winnerIds,
      },
    });

    await saveSession();
  },
}));
