import BiscaGame from "../classes/BiscaGame.js";
import axios from "axios";

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

class BiscaMatch {
  constructor(apiData, emitStateCallback, token) {
    this.id = apiData.id;
    this.emitStateCallback = emitStateCallback;
    this.token = token;
    this.stake = apiData.stake;
    this.type = apiData.type;
    this.status = apiData.status;

    this.player1Id = apiData.player1_user_id;
    this.player2Id = apiData.player2_user_id;

    this.marks = {
      [this.player1Id]: apiData.player1_marks || 0,
      [this.player2Id]: apiData.player2_marks || 0,
    };

    this.points = {
      [this.player1Id]: apiData.player1_points || 0,
      [this.player2Id]: apiData.player2_points || 0,
    };

    this.currentGame = null;
    this.GHOST_ID = 1;

    if (this.status === "Playing" && this.player2Id !== this.GHOST_ID) {
      this.startNewGame();
    }
  }

  async joinPlayer(userId) {
    if (this.player2Id !== this.GHOST_ID) return false;
    if (userId === this.player1Id) return false;

    this.player2Id = userId;
    this.marks[userId] = 0;
    this.points[userId] = 0;
    this.status = "Playing";

    await this.startNewGame();
    return true;
  }

  getAuthHeaders() {
    return {
      headers: { Authorization: this.token },
    };
  }

  async startNewGame() {
    console.log(`[Match ${this.id}] A iniciar nova mão (Game DB)...`);

    let newGameDbId = null;

    try {
      let payloadP1 = this.player1Id;
      let payloadP2 = this.player2Id;

      if (this.player2Id !== this.GHOST_ID) {
        console.log(
          "🔄 Multiplayer detetado: Trocando ordem para satisfazer a API..."
        );
        payloadP1 = this.player2Id;
        payloadP2 = this.player1Id;
      }

      const payload = {
        type: this.type,
        player1_user_id: payloadP1,
        player2_user_id: payloadP2,
        match_id: this.id,
        status: "Playing",
        began_at: new Date().toISOString(),
      };

      console.log("📤 [Payload Adaptado]:", JSON.stringify(payload, null, 2));

      const res = await axios.post(
        `${API_URL}/games`,
        payload,
        this.getAuthHeaders()
      );

      const gameData = res.data.game || res.data.data || res.data;
      newGameDbId = gameData.id;

      console.log(`[Match ${this.id}] Game DB criado: #${newGameDbId}`);

      const apiP1 = gameData.player1_user_id;
      const apiP2 = gameData.player2_user_id;

      const p1 = { id: apiP1, name: `User ${apiP1}` };
      const p2 = { id: apiP2, name: `User ${apiP2}` };

      this.currentGame = new BiscaGame(
        this.id,
        this.type,
        p1,
        p2,
        newGameDbId,
        (result) => {
          this.handleGameEnd(result);
        }
      );

      this.currentGame.init();

      if (this.emitStateCallback) {
        this.emitStateCallback("match:new-round", this.getState());
      }
    } catch (e) {
      if (e.response) {
        console.error(
          `❌ Erro API (${e.response.status}):`,
          JSON.stringify(e.response.data)
        );
      } else {
        console.error(`❌ Erro Código: ${e.message}`);
      }
    }
  }

  async handleGameEnd(result) {
    console.log(
      `[Match ${this.id}] Mão terminada. Vencedor: ${result.winnerId}`
    );

    this.points[result.player1_id] += result.player1_points;
    this.points[result.player2_id] += result.player2_points;

    if (this.currentGame && this.currentGame.dbId) {
      try {
        const payload = {
          status: "Ended",
          winner_user_id: result.winnerId,
          loser_user_id: result.loserId,
          is_draw: result.isDraw,
          player1_points: result.player1_points,
          player2_points: result.player2_points,
          ended_at: new Date().toISOString(),
        };

        console.log(
          `📤 A enviar update para Game #${this.currentGame.dbId}...`
        );

        // --- CORREÇÃO IMPORTANTE: Forçar o header aqui ---
        const config = {
          headers: {
            Authorization: this.token,
            "Content-Type": "application/json",
            Accept: "application/json",
          },
        };

        await axios.put(
          `${API_URL}/games/${this.currentGame.dbId}`,
          payload,
          config
        );

        console.log(
          `✅ Game #${this.currentGame.dbId} atualizado com sucesso.`
        );
      } catch (e) {
        // --- LOG DETALHADO PARA VER O MOTIVO DO 403 ---
        if (e.response) {
          console.error(`❌ ERRO CRÍTICO API (${e.response.status}):`);
          // Isto vai imprimir o JSON exato que o Laravel devolve
          console.error(JSON.stringify(e.response.data, null, 2));
        } else {
          console.error("Erro Axios:", e.message);
        }
      }
    } else {
      console.warn("⚠️ Ignorado: Não há ID de jogo na DB para atualizar.");
    }

    // ... (resto da lógica de atribuir marcas e finishMatch mantém-se igual)
    let marksToAdd = 0;
    let roundWinnerId = result.winnerId;

    if (roundWinnerId) {
      const winningScore =
        roundWinnerId == result.player1_id
          ? result.player1_points
          : result.player2_points;
      if (winningScore === 120) marksToAdd = 4;
      else if (winningScore > 90) marksToAdd = 2;
      else if (winningScore >= 60) marksToAdd = 1;
      this.marks[roundWinnerId] += marksToAdd;
    }

    if (this.marks[this.player1Id] >= 4 || this.marks[this.player2Id] >= 4) {
      await this.finishMatch();
      if (this.emitStateCallback) {
        this.emitStateCallback("match:ended", this.getState());
      }
    } else {
      console.log(`[Match ${this.id}] Ninguém ganhou 4 marcas. A baralhar...`);
      await this.startNewGame();
    }
  }

  async finishMatch() {
    this.status = "Ended";

    const winnerId =
      this.marks[this.player1Id] >= 4 ? this.player1Id : this.player2Id;
    const loserId =
      winnerId == this.player1Id ? this.player2Id : this.player1Id;

    try {
      await axios.put(
        `${API_URL}/matches/${this.id}`,
        {
          status: "Ended",
          winner_user_id: winnerId,
          loser_user_id: loserId,
          player1_marks: this.marks[this.player1Id],
          player2_marks: this.marks[this.player2Id],
          player1_points: this.points[this.player1Id],
          player2_points: this.points[this.player2Id],
        },
        this.getAuthHeaders()
      );
      console.log(`[Match ${this.id}] Encerrado com sucesso na API.`);
    } catch (e) {
      console.error(`Erro ao fechar Match API: ${e.message}`);
    }
  }

  playCard(userId, cardId) {
    if (!this.currentGame || this.status !== "Playing") return;
    return this.currentGame.playCard(userId, cardId);
  }

  getState() {
    let gameState = null;

    if (this.currentGame) {
      const p1Id = this.player1Id;
      const p2Id = this.player2Id;

      if (this.currentGame.players && this.currentGame.players[p1Id]) {
        gameState = this.currentGame.getStateForPlayer(p1Id);
      } else if (this.currentGame.players && this.currentGame.players[p2Id]) {
        gameState = this.currentGame.getStateForPlayer(p2Id);
      } else if (this.currentGame.players) {
        const availableIds = Object.keys(this.currentGame.players);
        if (availableIds.length > 0) {
          console.warn(
            `⚠️ [Match ${this.id}] IDs desalinhados! A usar vista do user ${availableIds[0]}`
          );
          gameState = this.currentGame.getStateForPlayer(availableIds[0]);
        }
      }
    }

    return {
      matchId: this.id,
      status: this.status,
      marks: this.marks,
      points: this.points,
      game: gameState,
    };
  }
}

export default BiscaMatch;
