import { Router } from "express";
import crypto from "crypto";
import { getDb } from "../../src/db";
import { authenticateToken } from "../../src/middleware/auth.middleware";
import { GachaSystem, DEFAULT_PITY, PityState, SonusResult } from "../../src/utils/GachaSystem";
import { getBannerById } from "../../src/config/banners.config";

export const gachaRouter = Router();

// ────────────────────────────────────────────────────────────────────────
// POST /api/gacha/pull
// Body: { bannerId: string, type: "x1" | "x10" | "event" }
// Returns: { results: SonusResult[], newPity: PityState }
// Also saves the results to player_sonus in the DB.
// ────────────────────────────────────────────────────────────────────────
gachaRouter.post("/pull", authenticateToken, async (req: any, res) => {
  const { bannerId, type } = req.body as { bannerId: string; type: "x1" | "x10" | "event" };

  if (!bannerId || !type) {
    return res.status(400).json({ error: "bannerId and type are required." });
  }

  const bannerConfig = getBannerById(bannerId);
  if (!bannerConfig) {
    return res.status(404).json({ error: `Banner '${bannerId}' not found.` });
  }

  try {
    const db = await getDb();
    const userId = req.user.id;

    // ── 1. Load current pity from DB ───────────────────────────────
    const profile = await db.get(
      "SELECT metadata FROM player_profiles WHERE user_id = ?",
      [userId]
    );

    let metadata: Record<string, any> = {};
    try { metadata = JSON.parse(profile?.metadata || "{}"); } catch { metadata = {}; }

    const pityKey = `pity_${bannerId}`;
    const currentPity: PityState = metadata[pityKey] ?? DEFAULT_PITY;

    // ── 2. Run gacha logic (server-side) ──────────────────────────
    let pullData: { results: SonusResult[]; newPity: PityState };
    if (type === "x10") {
      pullData = GachaSystem.pullStandard10(bannerId, currentPity);
    } else if (type === "x1") {
      pullData = GachaSystem.pullStandard1(bannerId, currentPity);
    } else {
      pullData = GachaSystem.pullEvent(bannerId);
    }

    // ── 3. Verificar límite de capacidad de inventario en el servidor ────
    const profileData = await db.get(
      "SELECT max_echo_capacity FROM player_profiles WHERE user_id = ?",
      [userId]
    );
    const maxCapacity = profileData?.max_echo_capacity ?? 100;

    const countRow = await db.get(
      "SELECT COUNT(*) as cnt FROM player_sonus WHERE user_id = ?",
      [userId]
    );
    const currentCount = countRow?.cnt ?? 0;
    const pullAmount = type === "x10" ? 10 : 1;

    if (currentCount + pullAmount > maxCapacity) {
      return res.status(400).json({
        code: "CAPACITY_EXCEEDED",
        error: `El límite de capacidad (${currentCount}/${maxCapacity}) ha sido alcanzado. Libera espacio o expande el inventario.`
      });
    }

    // ── 4. Persist pity ───────────────────────────────────────────
    metadata[pityKey] = pullData.newPity;
    await db.run(
      "UPDATE player_profiles SET metadata = ?, updated_at = CURRENT_TIMESTAMP WHERE user_id = ?",
      [JSON.stringify(metadata), userId]
    );

    // ── 5. Save pulled sonus to inventory (Cada personaje en slot aparte) ──
    await db.run("BEGIN TRANSACTION");
    try {
      for (const pull of pullData.results) {
        const master = await db.get(
          "SELECT * FROM sonus_master WHERE id_sonus = ?",
          [pull.id]
        );
        if (!master) continue;

        const idInstancia = crypto.randomUUID();
        await db.run(
          `INSERT INTO player_sonus
            (id_instancia, user_id, id_sonus, nivel_actual, experiencia_actual,
             cantidad_copias, nivel_evolucion, hp_actual, atk_actual, def_actual, spd_actual)
           VALUES (?, ?, ?, 1, 0, 1, 0, ?, ?, ?, ?)`,
          [idInstancia, userId, master.id_sonus,
           master.base_hp, master.base_atk, master.base_def, master.base_spd]
        );
      }
      await db.run("COMMIT");
    } catch (err) {
      await db.run("ROLLBACK");
      throw err;
    }

    // ── 5. Return results to client ───────────────────────────────
    res.json({
      results: pullData.results,
      newPity: pullData.newPity,
    });

  } catch (err: any) {
    console.error("Gacha pull error:", err);
    res.status(500).json({ error: "Gacha pull failed." });
  }
});

// ────────────────────────────────────────────────────────────────────────
// GET /api/gacha/pity/:bannerId
// Returns current pity state for a specific banner
// ────────────────────────────────────────────────────────────────────────
gachaRouter.get("/pity/:bannerId", authenticateToken, async (req: any, res) => {
  try {
    const db = await getDb();
    const userId = req.user.id;
    const { bannerId } = req.params;

    const profile = await db.get(
      "SELECT metadata FROM player_profiles WHERE user_id = ?",
      [userId]
    );

    let metadata: Record<string, any> = {};
    try { metadata = JSON.parse(profile?.metadata || "{}"); } catch { metadata = {}; }

    const pityKey = `pity_${bannerId}`;
    const pity: PityState = metadata[pityKey] ?? DEFAULT_PITY;

    res.json({ bannerId, pity });
  } catch (err) {
    console.error("Pity fetch error:", err);
    res.status(500).json({ error: "Failed to fetch pity." });
  }
});
