import { getMatch, addMatch } from "../state/match.js";
import BiscaMatch from "../classes/BiscaMatch.js";
import axios from "axios";

const API_URL = "http://localhost:8000/api/v1";

export default (io, socket) => {
  const createMatchEmitter = (matchId) => (eventName, payload) => {
    io.to(`match_${matchId}`).emit(eventName, payload);
  };

  socket.on("match:enter", async (data) => {
    const { matchId } = data;

    if (!socket.user || !socket.user.id) {
      return socket.emit("error", { message: "User not authenticated" });
    }

    const userId = socket.user.id;
    const room = `match_${matchId}`;

    let match = getMatch(matchId);

    if (!match) {
      try {
        console.log(`A pedir match ${matchId} à API...`);
        const res = await axios.get(`${API_URL}/matches/${matchId}`, {
          headers: { Authorization: socket.token },
        });

        const matchData = res.data.data || res.data;

        match = new BiscaMatch(
          matchData,
          createMatchEmitter(matchId),
          socket.token
        );
        addMatch(match);
        console.log(`Match ${matchId} carregado em memória.`);
      } catch (e) {
        console.error("Erro ao carregar Match da API:", e.message);
        socket.emit("error", "Match not found or API error");
        return;
      }
    } else {
      match.token = socket.token;
    }

    if (match) {
      match.token = socket.token;
    }

    match.emitStateCallback = createMatchEmitter(matchId);

    if (userId !== match.player1Id && match.player2Id === 1) {
      console.log(`User ${userId} a substituir o Ghost no Match ${matchId}`);
      await match.joinPlayer(userId);
    }

    socket.join(room);
    console.log(`Socket ${socket.id} entrou na sala ${room}`);

    if (match.status === "Playing") {
      socket.emit("match:update", match.getState());
    } else {
      socket.emit("match:waiting", { msg: "Waiting for opponent..." });
    }
  });

  socket.on("game:play-card", (data) => {
    const { matchId, cardId } = data;
    const match = getMatch(matchId);

    if (!match || match.status !== "Playing") {
      console.log(
        "Tentativa de jogar sem match ativo ou match não encontrado."
      );
      return;
    }

    const result = match.playCard(socket.user.id, cardId);

    if (result && result.error) {
      console.log(
        `❌ [Erro Jogo] User ${socket.user.id} tentou jogar carta ${cardId} mas: ${result.error}`
      );

      socket.emit("error", { message: result.error });
      return;
    }

    if (match.currentGame) {
      io.to(`match_${matchId}`).emit(
        "game:update",
        match.currentGame.getStateForPlayer(socket.user.id)
      );
    }
  });
  socket.on("debug:end-game", async (data) => {
    const { matchId } = data;
    const match = getMatch(matchId);
    if (match) {
      console.log(`[DEBUG] User ${socket.user.id} a forçar fim de jogo.`);
      // Simula que o user que clicou ganhou 120 pontos
      const winnerId = socket.user.id;
      const loserId =
        winnerId == match.player1Id ? match.player2Id : match.player1Id;

      // Objeto de resultado falso para fechar o jogo
      const fakeResult = {
        winnerId: winnerId,
        loserId: loserId,
        isDraw: false,
        player1_points: winnerId == match.player1Id ? 120 : 0,
        player2_points: winnerId == match.player2Id ? 120 : 0,
        player1_id: match.player1Id,
        player2_id: match.player2Id,
      };

      await match.handleGameEnd(fakeResult);
    }
  });

  // DEBUG: Forçar fim do Match Completo
  socket.on("debug:end-match", async (data) => {
    const { matchId } = data;
    const match = getMatch(matchId);
    if (match) {
      console.log(`[DEBUG] User ${socket.user.id} a forçar fim de MATCH.`);
      // Dá 4 marcas a quem clicou
      match.marks[socket.user.id] = 4;
      await match.finishMatch();

      // Emite o estado final
      io.to(`match_${matchId}`).emit("match:ended", match.getState());
    }
  });
};
