import { router, protectedProcedure } from '../_core/trpc.ts';
import { z } from 'zod';
import { createGame } from '../games/customGames.ts';
import { db } from '../db.ts';
import { walletTransactions, users } from '../../drizzle/schema.ts';
import { eq } from 'drizzle-orm';

export const customGamesRouter = router({
  /**
   * Spin a custom game
   */
  spin: protectedProcedure
    .input(
      z.object({
        gameId: z.string(),
        bet: z.number().min(0.1).max(1000),
      })
    )
    .mutation(async ({ ctx, input }) => {
      const { gameId, bet } = input;
      const userId = ctx.user.id;

      // Get user wallet
      const user = await db.query.users.findFirst({
        where: eq(users.id, userId),
      });

      if (!user || user.sweepCoins < bet) {
        throw new Error('Insufficient balance');
      }

      // Create game instance
      const serverSeed = Math.random().toString(36).substring(7);
      const game = createGame(gameId, serverSeed);

      // Execute spin
      const result = await game.spin();

      // Deduct bet
      const newBalance = user.sweepCoins - bet;
      await db.update(users).set({ sweepCoins: newBalance }).where(eq(users.id, userId));

      // Record transaction (bet)
      await db.insert(walletTransactions).values({
        userId,
        amount: -bet,
        type: 'game_bet',
        description: `Bet on ${game.getConfig().name}`,
        metadata: {
          gameId,
          bet,
          timestamp: new Date().toISOString(),
        },
      });

      // Credit win if any
      let finalBalance = newBalance;
      if (result.win > 0) {
        finalBalance = newBalance + result.win;
        await db.update(users).set({ sweepCoins: finalBalance }).where(eq(users.id, userId));

        // Record transaction (win)
        await db.insert(walletTransactions).values({
          userId,
          amount: result.win,
          type: 'game_win',
          description: `Won on ${game.getConfig().name}`,
          metadata: {
            gameId,
            win: result.win,
            multiplier: result.multiplier,
            bonusTriggered: result.bonusTriggered,
            timestamp: new Date().toISOString(),
          },
        });
      }

      return {
        reels: result.reels,
        win: result.win,
        multiplier: result.multiplier,
        bonusTriggered: result.bonusTriggered,
        bonusType: result.bonusType,
        freeSpins: result.freeSpins,
        newBalance: finalBalance,
        totalWin: result.win - bet,
      };
    }),

  /**
   * Get game info
   */
  getGameInfo: protectedProcedure.input(z.object({ gameId: z.string() })).query(({ input }) => {
    const serverSeed = Math.random().toString(36).substring(7);
    const game = createGame(input.gameId, serverSeed);
    const config = game.getConfig();

    return {
      id: config.id,
      name: config.name,
      description: `${config.name} - ${config.volatility} volatility`,
      reels: config.reels,
      symbolCount: config.symbols.length,
      paylines: config.paylines,
      rtp: config.rtp,
      volatility: config.volatility,
      minBet: config.minBet,
      maxBet: config.maxBet,
      maxWin: config.maxWin,
      bonusFeatures: config.bonusFeatures,
      payoutTable: game.getPayoutTable(),
    };
  }),

  /**
   * Get all custom games
   */
  getAllGames: protectedProcedure.query(() => {
    const gameIds = ['crystal-cascade', 'dragons-hoard', 'neon-lights', 'treasure-hunt', 'cosmic-reels'];

    return gameIds.map((gameId) => {
      const serverSeed = Math.random().toString(36).substring(7);
      const game = createGame(gameId, serverSeed);
      const config = game.getConfig();

      return {
        id: config.id,
        name: config.name,
        rtp: config.rtp,
        volatility: config.volatility,
        maxWin: config.maxWin,
        bonusFeatures: config.bonusFeatures,
      };
    });
  }),

  /**
   * Get game statistics
   */
  getGameStats: protectedProcedure
    .input(z.object({ gameId: z.string() }))
    .query(async ({ ctx, input }) => {
      const userId = ctx.user.id;

      // Get user's game transactions
      const transactions = await db.query.walletTransactions.findMany({
        where: (t) => t.userId === userId && t.metadata.gameId === input.gameId,
      });

      const bets = transactions.filter((t) => t.type === 'game_bet');
      const wins = transactions.filter((t) => t.type === 'game_win');

      const totalBet = bets.reduce((sum, t) => sum + Math.abs(t.amount), 0);
      const totalWin = wins.reduce((sum, t) => sum + t.amount, 0);

      return {
        totalSpins: bets.length,
        totalBet,
        totalWin,
        netProfit: totalWin - totalBet,
        winRate: wins.length / bets.length || 0,
        avgBet: totalBet / bets.length || 0,
        avgWin: totalWin / wins.length || 0,
        maxWin: Math.max(...wins.map((w) => w.amount), 0),
      };
    }),

  /**
   * Verify spin fairness
   */
  verifySpin: protectedProcedure
    .input(
      z.object({
        serverSeed: z.string(),
        clientSeed: z.string(),
        nonce: z.number(),
        expectedHash: z.string(),
      })
    )
    .query(({ input }) => {
      const { ProveablyFairRNG } = require('../customGameEngine.ts');

      const verified = ProveablyFairRNG.verifyFairness(
        input.serverSeed,
        input.clientSeed,
        input.nonce,
        input.expectedHash
      );

      return { verified };
    }),
});

export default customGamesRouter;
