import "server-only";

import { prisma } from "@/lib/prisma";
import { getScoringConfig } from "@/lib/scoring-config";
import { computeAssessmentSnapshot, type AssessmentSnapshot } from "@/lib/scoring-core";

export type { ModuleScoreSummary, AssessmentSnapshot } from "@/lib/scoring-core";

export async function recomputeAssessmentResults(userId: string): Promise<AssessmentSnapshot> {
  const diagnosticModules = await prisma.diagnosticModule.findMany({
    orderBy: [{ sortOrder: "asc" }, { name: "asc" }],
    select: {
      id: true,
      key: true,
      name: true,
      questions: {
        orderBy: [{ sortOrder: "asc" }, { createdAt: "asc" }],
        select: {
          id: true,
          answerOptions: {
            select: {
              weight: true,
            },
          },
        },
      },
    },
  });

  const allQuestionIds = diagnosticModules.flatMap((diagnosticModule) => diagnosticModule.questions.map((question) => question.id));

  const responses = allQuestionIds.length
    ? await prisma.response.findMany({
        where: {
          userId,
          questionId: {
            in: allQuestionIds,
          },
        },
        select: {
          questionId: true,
          answerOption: {
            select: {
              weight: true,
            },
          },
        },
      })
    : [];

  const selectedWeightByQuestionId = new Map(responses.map((response) => [response.questionId, response.answerOption.weight]));

  const modulesInput = diagnosticModules.map((diagnosticModule) => ({
    moduleId: diagnosticModule.id,
    moduleKey: diagnosticModule.key,
    moduleName: diagnosticModule.name,
    questionWeights: diagnosticModule.questions.map((question) => ({
      questionId: question.id,
      maxWeight: Math.max(...question.answerOptions.map((option) => option.weight), 1),
    })),
  }));

  const scoringConfig = await getScoringConfig();

  const snapshot = computeAssessmentSnapshot(modulesInput, selectedWeightByQuestionId, {
    overallScoreMethod: scoringConfig.overallScoreMethod,
    moduleWeights: scoringConfig.moduleWeights,
  });

  const calculatedAt = new Date();

  await prisma.$transaction(async (transaction) => {
    await transaction.assessmentResult.deleteMany({ where: { userId } });

    for (const moduleScore of snapshot.moduleScores) {
      await transaction.assessmentResult.create({
        data: {
          userId,
          moduleId: moduleScore.moduleId,
          moduleScore: moduleScore.score,
          calculatedAt,
          metadata: {
            completion: moduleScore.completion,
            answeredQuestions: moduleScore.answeredQuestions,
            totalQuestions: moduleScore.totalQuestions,
            status: moduleScore.status,
            scoringConfig: {
              overallScoreMethod: scoringConfig.overallScoreMethod,
            },
          },
        },
      });
    }

    await transaction.assessmentResult.create({
      data: {
        userId,
        overallScore: snapshot.overallScore,
        calculatedAt,
        metadata: {
          moduleCount: snapshot.moduleScores.length,
          answeredQuestions: snapshot.answeredQuestions,
          totalQuestions: snapshot.totalQuestions,
          scoringConfig: {
            overallScoreMethod: scoringConfig.overallScoreMethod,
          },
        },
      },
    });
  });

  return snapshot;
}
