const tables = require("../tables");

// --- Anti-cheat validation ---

// Max production théorique par seconde (5 generators maxés + click humain réaliste)
// Tier 5 = 150/s × 200 owned = 30 000/s (extreme case)
// Tous tiers cumulés extreme ≈ 50 000/s
// × prestige multiplier max réaliste (×10) = 500 000/s
// × evolution tree multiplier (×1.5) = 750 000/s
// Marge ×1.1 appliquée dans la validation
const MAX_PRODUCTION_PER_SECOND = 750_000;
const CHEAT_MARGIN = 1.1;

function validateGameState(gameState, previousSave) {
  // Vérification structurelle basique
  if (!gameState || typeof gameState !== "object") {
    return { valid: false, reason: "Invalid game state format" };
  }

  if (typeof gameState.resources !== "number" || gameState.resources < 0) {
    return { valid: false, reason: "Invalid resources value" };
  }

  if (!Array.isArray(gameState.generators)) {
    return { valid: false, reason: "Invalid generators" };
  }

  // Si pas de save précédente, c'est la première — accepter
  if (!previousSave) {
    return { valid: true };
  }

  // Calcul du temps écoulé depuis le dernier save
  const lastSaveTime = new Date(previousSave.last_save).getTime();
  const now = Date.now();
  const elapsedSeconds = Math.max((now - lastSaveTime) / 1000, 0);

  // Ressources max possibles = production max × temps × marge
  const maxPossibleResources =
    MAX_PRODUCTION_PER_SECOND * elapsedSeconds * CHEAT_MARGIN;

  // Comparer les ressources actuelles avec le maximum théorique
  // On compare le delta (gain depuis dernier save)
  const previousState = previousSave.game_state;
  const previousResources =
    typeof previousState === "object"
      ? previousState.resources ?? 0
      : 0;

  const resourceDelta = gameState.resources - previousResources;

  if (resourceDelta > maxPossibleResources && resourceDelta > 0) {
    return {
      valid: false,
      reason: `Resource gain (${Math.floor(resourceDelta)}) exceeds maximum possible (${Math.floor(maxPossibleResources)}) in ${Math.floor(elapsedSeconds)}s`,
    };
  }

  return { valid: true };
}

// --- Controllers ---

/**
 * GET /api/save
 * Charge la save du joueur connecté.
 */
const load = async (req, res) => {
  try {
    const userId = req.user;
    const save = await tables.game_saves.getByUserId(userId);

    if (!save) {
      return res.status(200).json({ gameState: null });
    }

    // game_state est stocké en JSON — MySQL le retourne comme objet si type JSON
    const gameState =
      typeof save.game_state === "string"
        ? JSON.parse(save.game_state)
        : save.game_state;

    return res.status(200).json({
      gameState,
      lastSave: save.last_save,
      lifetimeTadpoles: save.lifetime_tadpoles,
      prestigeCount: save.prestige_count,
      playTimeSeconds: save.play_time_seconds,
    });
  } catch (err) {
    console.error("save/load error:", err);
    return res.status(500).json({ message: "Failed to load save." });
  }
};

/**
 * POST /api/save
 * Sauvegarde le game state du joueur connecté.
 * Anti-cheat : valide le delta de ressources vs temps écoulé.
 */
const save = async (req, res) => {
  try {
    const userId = req.user;
    const { gameState, playTimeSeconds } = req.body;

    if (!gameState) {
      return res.status(400).json({ message: "gameState required." });
    }

    // Récupérer la save précédente pour validation
    const previousSave = await tables.game_saves.getByUserId(userId);

    // Valider l'état
    const validation = validateGameState(gameState, previousSave);
    if (!validation.valid) {
      console.warn(
        `Anti-cheat: user ${userId} rejected — ${validation.reason}`
      );
      return res.status(422).json({
        message: "Save rejected: anomaly detected.",
        reason: validation.reason,
      });
    }

    // Extraire les métadonnées pour la table
    const metadata = {
      lifetimeTadpoles: gameState.lifetimeTadpoles ?? 0,
      prestigeCount: gameState.prestigeCount ?? 0,
      playTimeSeconds: playTimeSeconds ?? 0,
    };

    await tables.game_saves.upsert(userId, gameState, metadata);

    return res.status(200).json({ message: "Save successful.", lastSave: new Date().toISOString() });
  } catch (err) {
    console.error("save/save error:", err);
    return res.status(500).json({ message: "Failed to save." });
  }
};

module.exports = { load, save };
