import { protectedProcedure, router } from "../_core/trpc.ts";
import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { getDb } from "../db.ts";
import { aiGeneratedGames } from "../../drizzle/schema.ts";
import { eq } from "drizzle-orm";
import { invokeLLM } from "../_core/llm.ts";
import { generateImage } from "../_core/imageGeneration.ts";

const adminProcedure = protectedProcedure.use(({ ctx, next }) => {
  if (ctx.user?.role !== "admin") throw new TRPCError({ code: "FORBIDDEN" });
  return next({ ctx });
});

export const aiGameBuilderRouter = router({
  analyzeGameUrl: adminProcedure
    .input(z.object({ gameUrl: z.string().url() }))
    .mutation(async ({ input }) => {
      try {
        const analysis = await invokeLLM({
          messages: [
            {
              role: "system",
              content:
                "You are a casino game expert. Analyze the provided game URL and extract detailed information about: game mechanics, symbols, bonus features, RTP, volatility, number of reels, paylines, and special features. Return structured JSON.",
            },
            {
              role: "user",
              content: `Analyze this casino game: ${input.gameUrl}. Provide detailed game analysis in JSON format with fields: gameName, symbols, bonusFeatures, rtp, volatility, reels, paylines, specialFeatures.`,
            },
          ],
          response_format: {
            type: "json_schema",
            json_schema: {
              name: "game_analysis",
              strict: true,
              schema: {
                type: "object",
                properties: {
                  gameName: { type: "string" },
                  symbols: { type: "array", items: { type: "string" } },
                  bonusFeatures: { type: "array", items: { type: "string" } },
                  rtp: { type: "number" },
                  volatility: { type: "string", enum: ["low", "medium", "high"] },
                  reels: { type: "number" },
                  paylines: { type: "number" },
                  specialFeatures: { type: "array", items: { type: "string" } },
                },
                required: ["gameName", "symbols", "bonusFeatures", "rtp", "volatility"],
                additionalProperties: false,
              },
            },
          },
        });

        const content = analysis.choices[0]?.message.content;
        if (!content) throw new Error("No response from LLM");
        const parsed = typeof content === "string" ? JSON.parse(content) : content;
        return parsed;
      } catch (error) {
        throw new TRPCError({
          code: "INTERNAL_SERVER_ERROR",
          message: `Failed to analyze game: ${error instanceof Error ? error.message : "Unknown error"}`,
        });
      }
    }),

  generateGameGraphics: adminProcedure
    .input(
      z.object({
        gameName: z.string(),
        symbols: z.array(z.string()),
        theme: z.string().optional(),
      })
    )
    .mutation(async ({ input }) => {
      try {
        const graphicsUrls: Record<string, string> = {};
        const theme = input.theme || "modern";

        // Generate thumbnail
        const thumbPrompt = `Create a casino slot game thumbnail for "${input.gameName}" with a ${theme} theme. Show 3 reels with colorful symbols. Professional, high-quality, 300x400px.`;
        const thumbnail = await generateImage({ prompt: thumbPrompt });
        if (thumbnail.url) graphicsUrls.thumbnail = thumbnail.url;

        // Generate symbol graphics
        for (const symbol of input.symbols.slice(0, 5)) {
          const symbolPrompt = `Create a casino slot game symbol: "${symbol}" with a ${theme} theme. Single symbol, 100x100px, high-quality, professional.`;
          const symbolImg = await generateImage({ prompt: symbolPrompt });
          if (symbolImg.url) graphicsUrls[symbol] = symbolImg.url;
        }

        return graphicsUrls;
      } catch (error) {
        throw new TRPCError({
          code: "INTERNAL_SERVER_ERROR",
          message: `Failed to generate graphics: ${error instanceof Error ? error.message : "Unknown error"}`,
        });
      }
    }),

  createCustomGame: adminProcedure
    .input(
      z.object({
        gameName: z.string(),
        originalGameUrl: z.string().optional(),
        rtp: z.number(),
        volatility: z.enum(["low", "medium", "high"]),
        symbols: z.array(z.string()),
        bonusFeatures: z.array(z.string()),
        reelGraphicsUrl: z.record(z.string(), z.string()).optional(),
        symbolGraphicsUrl: z.record(z.string(), z.string()).optional(),
        thumbnailUrl: z.string().optional(),
      })
    )
    .mutation(async ({ input }) => {
      const db = await getDb();
      if (!db) throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Database unavailable" });

      const gameSlug = `PlayCoinKrazy-${input.gameName.replace(/\s+/g, "-").toLowerCase()}`;

      const values: any = {
        gameName: input.gameName,
        gameSlug,
        rtp: input.rtp,
        volatility: input.volatility,
        aiAnalysis: JSON.stringify({ symbols: input.symbols, bonusFeatures: input.bonusFeatures }),
        reelSymbols: JSON.stringify(input.symbols),
        bonusFeatures: JSON.stringify(input.bonusFeatures),
        isActive: true,
        createdAt: new Date(),
        updatedAt: new Date(),
      };
      if (input.originalGameUrl) values.originalGameUrl = input.originalGameUrl;
      if (input.thumbnailUrl) values.thumbnailUrl = input.thumbnailUrl;
      if (input.reelGraphicsUrl) values.reelGraphicsUrl = JSON.stringify(input.reelGraphicsUrl);
      if (input.symbolGraphicsUrl) values.symbolGraphicsUrl = JSON.stringify(input.symbolGraphicsUrl);
      await db.insert(aiGeneratedGames).values(values);

      return { success: true, gameSlug };
    }),

  listAiGames: adminProcedure.query(async () => {
    const db = await getDb();
    if (!db) throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Database unavailable" });
    const games = await db.select().from(aiGeneratedGames);
    return games;
  }),

  toggleAiGame: adminProcedure
    .input(z.object({ gameId: z.number(), isActive: z.boolean() }))
    .mutation(async ({ input }) => {
      const db = await getDb();
      if (!db) throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Database unavailable" });
      await db
        .update(aiGeneratedGames)
        .set({ isActive: input.isActive })
        .where(eq(aiGeneratedGames.id, input.gameId));
      return { success: true };
    }),
});
