import { remixGame, generateGameAssets, generateGameCode, generateGameThumbnail } from "./gameBuilderService.ts";
import { db } from "../db.ts";
import { allGames } from "../../drizzle/schema.ts";

export interface RemixJob {
  id: string;
  theme: string;
  count: number;
  status: "pending" | "processing" | "completed" | "failed";
  progress: number;
  generatedGames: Array<{
    id: string;
    name: string;
    theme: string;
  }>;
  startedAt: Date;
  completedAt?: Date;
}

// In-memory job queue (in production, use a proper job queue like Bull)
const remixJobs: Map<string, RemixJob> = new Map();

/**
 * Game Remixer Bot - AI virtual employee that creates game variations
 * Automatically remixes existing games with new themes
 */
export class GameRemizerBot {
  /**
   * Start a remix job to create multiple game variations
   */
  static async startRemixJob(
    theme: string,
    count: number,
    userId: number
  ): Promise<RemixJob> {
    const jobId = `remix-${Date.now()}`;
    const job: RemixJob = {
      id: jobId,
      theme,
      count,
      status: "pending",
      progress: 0,
      generatedGames: [],
      startedAt: new Date(),
    };

    remixJobs.set(jobId, job);

    // Start async processing
    this.processRemixJob(jobId, theme, count, userId).catch((error) => {
      console.error(`Remix job ${jobId} failed:`, error);
      const job = remixJobs.get(jobId);
      if (job) {
        job.status = "failed";
        remixJobs.set(jobId, job);
      }
    });

    return job;
  }

  /**
   * Process remix job asynchronously
   */
  private static async processRemixJob(
    jobId: string,
    theme: string,
    count: number,
    userId: number
  ): Promise<void> {
    const job = remixJobs.get(jobId);
    if (!job) return;

    job.status = "processing";
    remixJobs.set(jobId, job);

    try {
      // Get base games to remix
      const baseGames = await db.query.allGames.findMany({
        where: (games, { eq }) => eq(games.isActive, true),
        limit: Math.min(count, 10),
      });

      if (baseGames.length === 0) {
        throw new Error("No base games available for remixing");
      }

      const generatedGames = [];

      // Remix each game
      for (let i = 0; i < count; i++) {
        const baseGame = baseGames[i % baseGames.length];
        const baseConfig = JSON.parse(baseGame.metadata || "{}").config;

        if (!baseConfig) continue;

        try {
          // Remix the game
          const remixedConfig = await remixGame(baseConfig, theme);

          // Generate unique ID for remixed game
          remixedConfig.id = `${remixedConfig.id}-${theme.toLowerCase().replace(/\s+/g, "-")}-${i + 1}`;
          remixedConfig.name = `${remixedConfig.name} - ${theme}`;

          // Generate assets
          const assets = await generateGameAssets(
            {
              theme,
              symbols: remixedConfig.symbols || [],
              reels: remixedConfig.reels,
              rows: remixedConfig.rows,
              paylines: remixedConfig.paylines,
              rtp: remixedConfig.rtp,
              volatility: remixedConfig.volatility,
              bonusFeatures: [],
              freeSpins: false,
              scatters: false,
              wilds: false,
              maxWin: 1000,
              animations: [],
              sounds: [],
              uiLayout: "",
            },
            remixedConfig.name
          );

          // Generate code
          const code = await generateGameCode(remixedConfig, {
            theme,
            symbols: remixedConfig.symbols || [],
            reels: remixedConfig.reels,
            rows: remixedConfig.rows,
            paylines: remixedConfig.paylines,
            rtp: remixedConfig.rtp,
            volatility: remixedConfig.volatility,
            bonusFeatures: [],
            freeSpins: false,
            scatters: false,
            wilds: false,
            maxWin: 1000,
            animations: [],
            sounds: [],
            uiLayout: "",
          });

          // Generate thumbnail
          const thumbnail = await generateGameThumbnail(
            remixedConfig.name,
            theme,
            (remixedConfig.symbols || []).map((s: any) => s.name)
          );

          // Register remixed game in database
          await db.insert(allGames).values({
            gameId: remixedConfig.id,
            name: remixedConfig.name,
            provider: "CoinKrazy Original",
            category: "slot",
            description: `${remixedConfig.name} - A ${theme} themed slot game`,
            rtp: remixedConfig.rtp,
            volatility: remixedConfig.volatility,
            reels: remixedConfig.reels,
            rows: remixedConfig.rows,
            paylines: remixedConfig.paylines,
            minBet: remixedConfig.minBet || 0.1,
            maxBet: remixedConfig.maxBet || 100,
            defaultBet: remixedConfig.defaultBet || 1,
            isActive: true,
            isFeatured: i < 3, // Feature first 3 remixed games
            metadata: JSON.stringify({
              config: remixedConfig,
              code,
              thumbnail,
              assets,
              baseGameId: baseGame.gameId,
              remixTheme: theme,
              createdBy: userId,
              createdAt: new Date().toISOString(),
              isRemixed: true,
            }),
          });

          generatedGames.push({
            id: remixedConfig.id,
            name: remixedConfig.name,
            theme,
          });

          // Update progress
          job.progress = Math.floor(((i + 1) / count) * 100);
          job.generatedGames = generatedGames;
          remixJobs.set(jobId, job);

          console.log(`✅ Remixed game ${i + 1}/${count}: ${remixedConfig.name}`);
        } catch (error) {
          console.error(`❌ Error remixing game ${i + 1}:`, error);
          // Continue with next game
        }
      }

      job.status = "completed";
      job.progress = 100;
      job.completedAt = new Date();
      remixJobs.set(jobId, job);

      console.log(`✅ Remix job ${jobId} completed! Created ${generatedGames.length} games`);
    } catch (error) {
      console.error(`❌ Remix job ${jobId} failed:`, error);
      job.status = "failed";
      remixJobs.set(jobId, job);
    }
  }

  /**
   * Get remix job status
   */
  static getJobStatus(jobId: string): RemixJob | null {
    return remixJobs.get(jobId) || null;
  }

  /**
   * Get all active remix jobs
   */
  static getAllJobs(): RemixJob[] {
    return Array.from(remixJobs.values());
  }

  /**
   * Schedule weekly automatic remix jobs
   * This would typically be called by a cron job or scheduler
   */
  static async scheduleWeeklyRemix(userId: number): Promise<void> {
    const themes = [
      "Underwater Adventure",
      "Space Odyssey",
      "Medieval Kingdom",
      "Tropical Paradise",
      "Cyberpunk Future",
      "Ancient Civilizations",
      "Enchanted Forest",
      "Wild West",
      "Asian Dragons",
      "Mystical Legends",
    ];

    console.log("🤖 Game Remixer Bot starting weekly remix cycle...");

    for (const theme of themes) {
      try {
        const job = await this.startRemixJob(theme, 3, userId);
        console.log(`🎮 Started remix job for theme: ${theme} (Job ID: ${job.id})`);
        
        // Stagger jobs to avoid overwhelming the system
        await new Promise((resolve) => setTimeout(resolve, 2000));
      } catch (error) {
        console.error(`Error starting remix job for theme ${theme}:`, error);
      }
    }

    console.log("✅ Weekly remix cycle scheduled!");
  }

  /**
   * Get remix job statistics
   */
  static getStats() {
    const jobs = Array.from(remixJobs.values());
    const completed = jobs.filter((j) => j.status === "completed").length;
    const processing = jobs.filter((j) => j.status === "processing").length;
    const failed = jobs.filter((j) => j.status === "failed").length;
    const totalGamesCreated = jobs.reduce((sum, j) => sum + j.generatedGames.length, 0);

    return {
      totalJobs: jobs.length,
      completed,
      processing,
      failed,
      totalGamesCreated,
      averageGamesPerJob: jobs.length > 0 ? totalGamesCreated / jobs.length : 0,
    };
  }
}

export default GameRemizerBot;
