import { protectedProcedure, router } from "../_core/trpc.ts";
import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { getDb } from "../db.ts";
import { casinoGames, gameAnalytics } from "../../drizzle/schema.ts";
import { eq, desc } from "drizzle-orm";

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

export const gameManagementRouter = router({
  listGames: adminProcedure
    .input(z.object({ limit: z.number().default(50), offset: z.number().default(0) }).optional())
    .query(async ({ input }) => {
      const db = await getDb();
      if (!db) throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Database unavailable" });
      const games = await db.select().from(casinoGames).limit(input?.limit || 50).offset(input?.offset || 0);
      return games;
    }),

  getGameAnalytics: adminProcedure
    .input(z.object({ gameId: z.number() }))
    .query(async ({ input }) => {
      const db = await getDb();
      if (!db) throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Database unavailable" });
      const analytics = await db.select().from(gameAnalytics).where(eq(gameAnalytics.gameId, input.gameId)).limit(1);
      return analytics[0] || null;
    }),

  toggleGame: 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(casinoGames).set({ isActive: input.isActive }).where(eq(casinoGames.id, input.gameId));
      return { success: true };
    }),

  updateGameSettings: adminProcedure
    .input(
      z.object({
        gameId: z.number(),
        title: z.string().optional(),
        rtp: z.number().optional(),
        volatility: z.enum(["low", "medium", "high", "very_high"]).optional(),
        maxBetGc: z.number().optional(),
        minBetGc: z.number().optional(),
        isFeatured: z.boolean().optional(),
      })
    )
    .mutation(async ({ input }) => {
      const db = await getDb();
      if (!db) throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Database unavailable" });
      const updates: any = {};
      if (input.title) updates.title = input.title;
      if (input.rtp) updates.rtp = input.rtp;
      if (input.volatility) updates.volatility = input.volatility;
      if (input.maxBetGc) updates.maxBetGc = input.maxBetGc;
      if (input.minBetGc) updates.minBetGc = input.minBetGc;
      if (input.isFeatured !== undefined) updates.isFeatured = input.isFeatured;
      await db.update(casinoGames).set(updates).where(eq(casinoGames.id, input.gameId));
      return { success: true };
    }),

  getAnalyticsDashboard: adminProcedure.query(async () => {
    const db = await getDb();
    if (!db) throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Database unavailable" });
    const analytics = await db.select().from(gameAnalytics).orderBy(desc(gameAnalytics.totalRevenue)).limit(10);
    return {
      topGames: analytics,
      totalRevenue: analytics.reduce((sum, g) => sum + (Number(g.totalRevenue) || 0), 0),
      totalSpins: analytics.reduce((sum, g) => sum + (g.totalSpins || 0), 0),
      avgRtp: analytics.length > 0 ? analytics.reduce((sum, g) => sum + (Number(g.rtp) || 0), 0) / analytics.length : 0,
    };
  }),

  createCustomGame: adminProcedure
    .input(
      z.object({
        title: z.string(),
        provider: z.string(),
        rtp: z.number(),
        volatility: z.enum(["low", "medium", "high", "very_high"]),
        features: z.array(z.string()).optional(),
        minBetGc: z.number().default(1),
        maxBetGc: z.number().default(1000),
      })
    )
    .mutation(async ({ input }) => {
      const db = await getDb();
      if (!db) throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Database unavailable" });
      const slug = input.title.toLowerCase().replace(/\s+/g, "-");
      await db.insert(casinoGames).values({
        slug,
        title: input.title,
        provider: input.provider,
        category: "new",
        rtp: input.rtp,
        volatility: input.volatility,
        features: input.features ? JSON.stringify(input.features) : null,
        minBetGc: input.minBetGc,
        maxBetGc: input.maxBetGc,
        isActive: 1,
        createdAt: new Date(),
      } as any);
      return { success: true };
    }),
});
