import { dbConnection } from "db";
import type { NextApiRequest, NextApiResponse } from "next";
import { IStakingSource } from "typings";
import { gameConfig } from "@/utils/gameLogic";
import { updateAllToCamelCase } from "@/utils/helpers";
import {
  generateRandomBase64String,
} from "../../../../utils/helpers";

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  try {
    if (req.method === "GET") {
      const { userId } = req.query;
      const db = await dbConnection;
      const sourcesSql = `
        SELECT id, name, description FROM staking_source
        WHERE staking_source.user_id = ?`;
      const stakingSources = await db.all(sourcesSql, [userId]);
      for (const source of stakingSources) {
        const wellsSql = `
          SELECT id, resname as resourceType, supply FROM resource_well
          WHERE source_id = ?`;
        const resourceWells = await db.all(wellsSql, [source.id]);
        source.resourceWells = resourceWells;
        const stakesSql = `
          SELECT staking_event.id, resname as resourceType, source_id as stakingSourceId,
                 inventory_item_id as inventoryItemId, duration_in_mins as durationInMins,
                 stake_amount as stakeAmount, staking_event.created_at as startTime
          FROM staking_event
          INNER JOIN resource_well ON well_id = resource_well.id
          INNER JOIN staking_source ON source_id = staking_source.id
          LEFT JOIN claim_event ON staking_event.id = claim_event.staking_event_id
          WHERE staking_source.id = ? AND claim_event.staking_event_id IS NULL;`;
        const activeStakes = await db.all(stakesSql, [source.id]);

        source.activeStakes = activeStakes;
      }
      
      return res.status(200).json(stakingSources);
    }
    if (req.method === "POST") {
      const { userId } = req.query;
      const db = await dbConnection;

      try {
        const randomName = "Moon 1";
        const randomDescription = "This is a moon orbiting Selene's planet";
        const randomKey = "0x" + generateRandomBase64String(16);
        const resMax = gameConfig.moons.resourceMaxStartAmount;
        const resMin = gameConfig.moons.resourceMinStartAmount;
        const moonPrice = gameConfig.moons.price;

        await db.run("BEGIN");
        await db.run(`UPDATE bank_account SET balance = balance - ?
                      WHERE user_id = ?`, [moonPrice, userId]);
        const result = await db.run(`INSERT INTO staking_source(user_id, name, description, address)
                                     VALUES (?, ?, ?, ?)`, [userId, randomName, randomDescription, randomKey]);
        const sourceId = result.lastID;
        for (const resname of gameConfig.resources) {
          if (Math.random() < gameConfig.moons.resourceChance) {
            const randomNumber = Math.random();
            const range = resMax - resMin + 1;
            const initSupply = Math.floor(Math.random() * range + resMin);
            await db.run(`INSERT INTO resource_well (source_id, resname, supply)
                          VALUES (?, ?, ?)`, [sourceId, resname, initSupply]);
          }
        }
        await db.run("COMMIT");
        return res.status(200).json({"stakingSourceId": sourceId});
      } catch (error) {
        await db.exec("ROLLBACK");
        if (error.message.includes("CHECK constraint failed")) {
          return res.status(400).json({ "error": "Insuficcient funds" });
        } else {
          return res.status(400).json({ "error": error.message });  
        }
      }
    }
  } catch (error) {
    res.status(500).json(error.message);
  }
}
