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

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

export const achievementsRouter = router({
  listAchievements: protectedProcedure.query(async () => {
    const db = await getDb();
    if (!db) throw new TRPCError({ code: "INTERNAL_SERVER_ERROR" });
    return await db.select().from(achievements);
  }),

  getUserAchievements: protectedProcedure.query(async ({ ctx }) => {
    const db = await getDb();
    if (!db) throw new TRPCError({ code: "INTERNAL_SERVER_ERROR" });
    return await db.select().from(userAchievements).where(eq(userAchievements.userId, ctx.user!.id));
  }),

  unlockAchievement: protectedProcedure
    .input(z.object({ achievementId: z.number() }))
    .mutation(async ({ ctx, input }) => {
      const db = await getDb();
      if (!db) throw new TRPCError({ code: "INTERNAL_SERVER_ERROR" });

      const existing = await db
        .select()
        .from(userAchievements)
        .where(eq(userAchievements.userId, ctx.user!.id))
        .limit(1);

      if (existing.length > 0) return { success: false, message: "Already unlocked" };
      
      // Check if achievement exists
      const ach = await db.select().from(achievements).where(eq(achievements.id, input.achievementId)).limit(1);
      if (!ach[0]) throw new TRPCError({ code: "NOT_FOUND", message: "Achievement not found" });

      await db.insert(userAchievements).values({
        userId: ctx.user!.id,
        achievementId: input.achievementId,
        unlockedAt: new Date(),
        rewardClaimed: false,
      } as any);

      return { success: true };
    }),

  claimReward: protectedProcedure
    .input(z.object({ userAchievementId: z.number() }))
    .mutation(async ({ ctx, input }) => {
      const db = await getDb();
      if (!db) throw new TRPCError({ code: "INTERNAL_SERVER_ERROR" });

      await db
        .update(userAchievements)
        .set({ rewardClaimed: true })
        .where(eq(userAchievements.id, input.userAchievementId));

      return { success: true };
    }),

  createAchievement: adminProcedure
    .input(
      z.object({
        name: z.string(),
        description: z.string().optional(),
        category: z.enum(["gameplay", "social", "spending", "milestone", "special"]),
        condition: z.string(),
        rewardSc: z.number().default(0),
        rewardGc: z.number().default(0),
      })
    )
    .mutation(async ({ input }) => {
      const db = await getDb();
      if (!db) throw new TRPCError({ code: "INTERNAL_SERVER_ERROR" });

      await db.insert(achievements).values({
        name: input.name,
        description: input.description,
        category: input.category,
        condition: input.condition,
        rewardSc: input.rewardSc,
        rewardGc: input.rewardGc,
        isActive: true,
        createdAt: new Date(),
      } as any);

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