// server_roll.js
import { Server } from "socket.io";
import {BASE_URL} from "../constants/index.js";

function generateId(length = 32) {
  const chars =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  let result = "";
  for (let i = 0; i < length; i++) {
    result += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  return result;
}

const io = new Server(3002, {
  cors: {
    origin: ["http://localhost:3002"],
    methods: ["GET", "POST"],
  },
});


const ROUND_DURATION = 20;
const BREAK_DURATION = 10;
let activeTierBySocket = {}; // socket.id -> tierKey

const SPIN_DURATION_MS = 3500;

// ✅ tiers list (same ids as frontend tiers[])
const TIER_KEYS = ["tier-2x", "tier-14x", "tier-7x", "tier-2x-red"];

let roundId = 1;
let winnerTier = null;

let state = {
  phase: "countdown", // countdown | break
  durationSec: ROUND_DURATION,
  endAt: Date.now() + ROUND_DURATION * 1000,
  serverNow: Date.now(),
  playersByTier: {},
  spin: null,
  lastResult: null,
  game_id : generateId(),
};

let interval = null;
let players = [];

function emitTimer() {
  state.serverNow = Date.now();
  io.emit("roll:timer", {
    phase: state.phase,
    durationSec: state.durationSec,
    endAt: state.endAt,
    serverNow: state.serverNow,
    spin: state.spin,
    lastResult: state.lastResult,
  });
  // ✅ yeh UI update karega (JoinGamePanel)
  emitPlayers();
}

function emitPlayers() {
  io.emit("updatePlayers", structuredClone(state.playersByTier));
}

function startCountdown() {
  activeTierBySocket = {};
  state.playersByTier = {};
  state.spin = null;
  state.roundId = generateId();
  emitPlayers();

  state.phase = "countdown";
  state.durationSec = ROUND_DURATION;
  state.endAt = Date.now() + ROUND_DURATION * 1000;

  emitTimer();

  if (interval) clearInterval(interval);
  interval = setInterval(() => {
    emitTimer();
    if (Date.now() >= state.endAt) {
      clearInterval(interval);
      startBreak();
    }
  }, 250);
}

function removePlayerFromAllTiers(socketId) {
  Object.keys(state.playersByTier).forEach((t) => {
    state.playersByTier[t] = (state.playersByTier[t] || []).filter(
      (p) => p.id !== socketId,
    );
    if (state.playersByTier[t].length === 0) delete state.playersByTier[t];
  });
}

function startBreak() {
  winnerTier = TIER_KEYS[Math.floor(Math.random() * TIER_KEYS.length)];

  const startAt = Date.now() + 200;
  const stopAt = startAt + SPIN_DURATION_MS; // exact stop time

  state.spin = { roundId, winnerTier, startAt, stopAt };

  state.lastResult = { roundId, winnerTier, stopAt };
  state.phase = "break";
  state.durationSec = BREAK_DURATION;
  state.endAt = Date.now() + BREAK_DURATION * 1000;

  io.emit("roll:spinSchedule", { ...state.spin, serverNow: Date.now() });

  emitTimer();

  if (interval) clearInterval(interval);
  interval = setInterval(() => {
    emitTimer();

    if (Date.now() >= state.endAt) {
      clearInterval(interval);
      roundId += 1;
      startCountdown();
    }
  }, 250);
}

function ensureTier(tier) {
  if (!state.playersByTier[tier]) state.playersByTier[tier] = [];
}

function upsertPlayerInTier(socketId, tier, patch) {
  ensureTier(tier);
  const arr = state.playersByTier[tier];
  const idx = arr.findIndex((p) => p.id === socketId);

  if (idx === -1) {
    arr.push({
      id: socketId,
      name: patch.name || "Player",
      image: patch.image,
      tier,
      cards: patch.cards || [],
      totalValue: Number(patch.totalValue || 0),
    });
  } else {
    arr[idx] = { ...arr[idx], ...patch };
  }
}

io.on("connection", (socket) => {
  socket.emit("roll:timer", { ...state, serverNow: Date.now() });
  emitPlayers()

  socket.on("roll:enter", () => {
    if (!interval) startCountdown();
  });

  socket.on("requestRollTimer", () => {
    socket.emit("roll:timer", {
      phase: state.phase,
      durationSec: state.durationSec,
      endAt: state.endAt,
      serverNow: Date.now(),
      spin: state.spin,
      lastResult: state.lastResult, // ✅ add
    });

    emitPlayers();
  });

  // ✅ 1) user tier select karta hai
  socket.on("joinGame", ({ name, tier, image, user_id, cards }) => {
    if (state.phase !== "countdown") return;
    removePlayerFromAllTiers(socket.id);
    // ✅ set new active tier
    activeTierBySocket[socket.id] = tier;
    console.log();
    // upsertPlayerInTier(socket.id, tier, {
    //   user_id,
    //   name,
    //   tier,
    //   image,
    //   cards: tier.cards,
    //   totalValue: tier.totalValue,
    // });
    // joinPlayer(player, state.roundId);
    // console.log("Joined Player",players);

    emitPlayers();
  });

  // ✅ 2) user cards select karke PLAY GAME dabata hai
  socket.on("playCard", (payload) => {
    if (state.phase !== "countdown") return;

    const tier = activeTierBySocket[socket.id];
    if (!tier) return;

    let player = {
      game_id : state.game_id,
      user_id : payload.userId,
      name : payload.name,
      image: payload.image,
      multiplier : payload.tier,
      cards : payload.cards,
      totalValue : payload.totalValue,
      status : "join",
    }
    // const is_player = players.find(p => p.user_id === payload.userId);
    players = players.map(p =>
      p.user_id === payload.userId
        ? { ...p, multiplier: payload.tier, cards:payload.cards }
        : p
    );
    players.push(player);
    joinPlayer(player, state.game_id);
    console.log(payload);
    upsertPlayerInTier(socket.id, tier, {
      name: payload?.name,
      image: payload?.image,
      tier,
      cards: payload?.cards ? JSON.parse(payload?.cards) : [],
      totalValue: Number(payload?.totalValue || 0),
    });
    emitPlayers();
  });

  socket.on("winstate", (winnerTier)=>{
    players = [];
    updatePlayer(state.game_id, winnerTier);
    state.game_id =  generateId();
  });

  socket.on("cancelJoin", () => {
    delete activeTierBySocket[socket.id];
    removePlayerFromAllTiers(socket.id);
    emitPlayers();
  });

  socket.on("disconnect", () => {
    delete activeTierBySocket[socket.id]; // ✅ cleanup mapping too

    removePlayerFromAllTiers(socket.id);
    emitPlayers();
  });
});

startCountdown();

async function joinPlayer(player, game_id){
  try {
    const response = await fetch(BASE_URL+"/api/roll-join", {
    method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        game_id: game_id,
        user_id: player.user_id,
        multiplier: player.multiplier,
        cards: JSON.stringify(player.cards),
        status: player.status,
        players: players,
      }),
    });

    if (!response.ok) {
      console.log(response);
    }

    const text = await response.text(); // 🔥 read once

    const data = text ? JSON.parse(text) : null;
    console.log(data);
    return data;
  }catch(error){
    console.log(error);
    return {
      success: false,
      message: error.message || "Something went wrong",
    };
  }
}

async function updatePlayer(game_id, tier){
  try {
      const response = await fetch(BASE_URL+"/api/roll-update", {
      method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        }, 
        body: JSON.stringify({
          game_id: game_id,
          multiplier: tier,
        }),
      });

      if (!response.ok) {
        console.log(response);
      }
      const data = await response.json();
      console.log(data);
      return data;
    }catch(error){
      console.log(error);
      return {
        success: false,
        message: error.message || "Something went wrong",
      };
  }
}
