import { getDb } from "../db.ts";
import { allGames, gameLibrary, gameStats, gameRecommendations } from "../../drizzle/schema.ts";
import { eq, and, desc, like } from "drizzle-orm";
import * as fs from "fs";
import * as path from "path";

const allGamesConfigPath = path.join(path.dirname(new URL(import.meta.url).pathname), "all-games-config.json");
const allGamesConfigData = fs.readFileSync(allGamesConfigPath, "utf-8");
const allGamesConfig = JSON.parse(allGamesConfigData);

/**
 * Initialize all games in the database from config
 */
export async function initializeAllGames() {
  const db = await getDb();
  if (!db) return false;

  try {
    for (const game of allGamesConfig.games) {
      // Check if game already exists
      const existing = await db
        .select()
        .from(allGames)
        .where(eq(allGames.gameId, game.id))
        .limit(1);

      if (!existing.length) {
        await db.insert(allGames).values({
          gameId: game.id,
          gameName: game.name,
          gameType: game.type,
          category: game.category,
          provider: game.provider,
          rtp: game.rtp.toString(),
          volatility: game.volatility,
          paylines: game.paylines,
          reels: game.reels,
          minBet: game.minBet.toString(),
          maxBet: game.maxBet.toString(),
          hasIcon: game.hasIcon ? 1 : 0,
          isActive: game.isActive ? 1 : 0,
          isFeatured: game.isFeatured ? 1 : 0,
        });
      }
    }
    console.log(`[AllGames] Initialized ${allGamesConfig.games.length} games`);
    return true;
  } catch (error) {
    console.error("[AllGames] Error initializing games:", error);
    return false;
  }
}

/**
 * Get all games with optional filtering
 */
export async function getAllGames(filters?: {
  provider?: string;
  category?: string;
  volatility?: string;
  featured?: boolean;
  search?: string;
}) {
  const db = await getDb();
  if (!db) return [];

  let query = db.select().from(allGames).where(eq(allGames.isActive, 1));

  if (filters?.provider) {
    query = query.where(eq(allGames.provider, filters.provider));
  }
  if (filters?.category) {
    query = query.where(eq(allGames.category, filters.category));
  }
  if (filters?.volatility) {
    query = query.where(eq(allGames.volatility, filters.volatility));
  }
  if (filters?.featured) {
    query = query.where(eq(allGames.isFeatured, 1));
  }
  if (filters?.search) {
    query = query.where(like(allGames.gameName, `%${filters.search}%`));
  }

  return query.orderBy(desc(allGames.playCount));
}

/**
 * Get game by ID
 */
export async function getGameById(gameId: string) {
  const db = await getDb();
  if (!db) return null;

  const result = await db
    .select()
    .from(allGames)
    .where(eq(allGames.gameId, gameId))
    .limit(1);

  return result[0] || null;
}

/**
 * Add game to user's library
 */
export async function addToGameLibrary(userId: number, gameId: string) {
  const db = await getDb();
  if (!db) return false;

  try {
    // Check if already in library
    const existing = await db
      .select()
      .from(gameLibrary)
      .where(and(eq(gameLibrary.userId, userId), eq(gameLibrary.gameId, gameId)))
      .limit(1);

    if (!existing.length) {
      await db.insert(gameLibrary).values({
        userId,
        gameId,
      });
    }
    return true;
  } catch (error) {
    console.error("[AllGames] Error adding to library:", error);
    return false;
  }
}

/**
 * Get user's game library
 */
export async function getUserGameLibrary(userId: number) {
  const db = await getDb();
  if (!db) return [];

  return db
    .select()
    .from(gameLibrary)
    .where(eq(gameLibrary.userId, userId))
    .orderBy(desc(gameLibrary.lastPlayedAt));
}

/**
 * Update game play stats
 */
export async function updateGameStats(
  gameId: string,
  userId: number,
  betAmount: number,
  winAmount: number
) {
  const db = await getDb();
  if (!db) return false;

  try {
    // Update game library
    const existing = await db
      .select()
      .from(gameLibrary)
      .where(and(eq(gameLibrary.userId, userId), eq(gameLibrary.gameId, gameId)))
      .limit(1);

    if (existing.length) {
      const current = existing[0];
      await db
        .update(gameLibrary)
        .set({
          lastPlayedAt: new Date(),
          playCount: (current.playCount || 0) + 1,
          totalBet: (parseFloat(current.totalBet?.toString() || "0") + betAmount).toString(),
          totalWin: (parseFloat(current.totalWin?.toString() || "0") + winAmount).toString(),
        })
        .where(and(eq(gameLibrary.userId, userId), eq(gameLibrary.gameId, gameId)));
    }

    // Update global game stats
    const today = new Date().toISOString().split("T")[0];
    const dailyStats = await db
      .select()
      .from(gameStats)
      .where(and(eq(gameStats.gameId, gameId), eq(gameStats.date, today)))
      .limit(1);

    if (dailyStats.length) {
      const current = dailyStats[0];
      await db
        .update(gameStats)
        .set({
          playCount: (current.playCount || 0) + 1,
          totalBet: (parseFloat(current.totalBet?.toString() || "0") + betAmount).toString(),
          totalWin: (parseFloat(current.totalWin?.toString() || "0") + winAmount).toString(),
        })
        .where(and(eq(gameStats.gameId, gameId), eq(gameStats.date, today)));
    } else {
      await db.insert(gameStats).values({
        gameId,
        date: today,
        playCount: 1,
        totalBet: betAmount.toString(),
        totalWin: winAmount.toString(),
      });
    }

    // Update game total stats
    const game = await getGameById(gameId);
    if (game) {
      await db
        .update(allGames)
        .set({
          playCount: (game.playCount || 0) + 1,
          totalWinnings: (parseFloat(game.totalWinnings?.toString() || "0") + winAmount).toString(),
        })
        .where(eq(allGames.gameId, gameId));
    }

    return true;
  } catch (error) {
    console.error("[AllGames] Error updating stats:", error);
    return false;
  }
}

/**
 * Get game recommendations for user
 */
export async function getGameRecommendations(userId: number, limit: number = 10) {
  const db = await getDb();
  if (!db) return [];

  // Get user's favorite volatility from play history
  const userLibrary = await getUserGameLibrary(userId);
  if (!userLibrary.length) {
    // Return featured games for new users
    return getAllGames({ featured: true });
  }

  // Get high-RTP games user hasn't played
  const playedGameIds = userLibrary.map((g) => g.gameId);
  const allGamesList = await getAllGames();
  const unplayedHighRtp = allGamesList
    .filter((g) => !playedGameIds.includes(g.gameId) && parseFloat(g.rtp?.toString() || "0") > 96.5)
    .slice(0, limit);

  return unplayedHighRtp;
}

/**
 * Get games by provider
 */
export async function getGamesByProvider(provider: string) {
  return getAllGames({ provider });
}

/**
 * Get featured games
 */
export async function getFeaturedGames() {
  return getAllGames({ featured: true });
}

/**
 * Search games
 */
export async function searchGames(query: string) {
  return getAllGames({ search: query });
}

/**
 * Get game statistics
 */
export async function getGameStatistics(gameId: string, days: number = 7) {
  const db = await getDb();
  if (!db) return null;

  const startDate = new Date();
  startDate.setDate(startDate.getDate() - days);
  const startDateStr = startDate.toISOString().split("T")[0];

  const stats = await db
    .select()
    .from(gameStats)
    .where(and(eq(gameStats.gameId, gameId)))
    .orderBy(desc(gameStats.date));

  return stats;
}

// Initialize games on service load
initializeAllGames().catch(console.error);
