import { Worker } from "bullmq";
import { redisConnectionOpts } from "../connection.js";
import { awardPoints, revokePoints, checkAchievements } from "../../lib/gamification.js";
import { db } from "../../db/connection.js";
import { logger } from "../../lib/logger.js";
import type { POINT_VALUES } from "../../lib/gamification.js";

const log = logger.child({ component: "gamification-worker" });

export type GamificationJobData =
  | { job: "awardPoints"; userId: string; action: keyof typeof POINT_VALUES; recordingId?: string }
  | { job: "revokePoints"; userId: string; action: keyof typeof POINT_VALUES; recordingId?: string }
  | { job: "checkAchievements"; userId: string; category?: string };

export function startGamificationWorker(): Worker {
  const worker = new Worker(
    "gamification",
    async (bullJob) => {
      const data = bullJob.data as GamificationJobData;
      log.info(
        { jobId: bullJob.id, job: data.job, userId: data.userId },
        "Processing gamification job",
      );

      switch (data.job) {
        case "awardPoints":
          await awardPoints(db, data.userId, data.action, data.recordingId);
          break;
        case "revokePoints":
          await revokePoints(db, data.userId, data.action, data.recordingId);
          break;
        case "checkAchievements":
          await checkAchievements(db, data.userId, data.category);
          break;
        default:
          throw new Error(`Unknown gamification job: ${(data as GamificationJobData).job}`);
      }

      log.info({ jobId: bullJob.id, job: data.job }, "Gamification job completed");
    },
    { connection: redisConnectionOpts },
  );

  worker.on("failed", (bullJob, err) => {
    log.error(
      { jobId: bullJob?.id, job: (bullJob?.data as GamificationJobData)?.job, err: err.message },
      "Gamification job failed",
    );
  });

  return worker;
}
