import { NextResponse } from "next/server";
import { db } from "@/db";
import { quizSessions } from "@/db/schema";
import { eq, and, gte } from "drizzle-orm";
import { getSession } from "@/lib/auth";
import {
  drawQuizQuestions,
  QUIZ_QUESTIONS,
  type QuizQuestion,
} from "@/lib/quiz-questions";

const QUIZ_EXPIRY_MS = 2 * 60 * 60 * 1000; // 2 hours

interface StoredAnswer {
  questionId: string;
  answer: string;
  correct: boolean;
}

export async function GET() {
  const session = await getSession();
  if (!session) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const cutoff = new Date(Date.now() - QUIZ_EXPIRY_MS);

  const [passedQuiz] = await db
    .select()
    .from(quizSessions)
    .where(
      and(
        eq(quizSessions.annotatorId, session.annotatorId),
        eq(quizSessions.passed, true),
        gte(quizSessions.startedAt, cutoff),
      ),
    )
    .orderBy(quizSessions.startedAt)
    .limit(1);

  if (passedQuiz) {
    return NextResponse.json({
      hasPassedQuiz: true,
      quizSessionId: passedQuiz.id,
    });
  }

  return NextResponse.json({ hasPassedQuiz: false });
}

export async function POST(request: Request) {
  const session = await getSession();
  if (!session) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const body = await request.json();
  const { action } = body as { action: string };

  if (action === "start") {
    return handleStart(session.annotatorId);
  }

  if (action === "answer") {
    const { quizSessionId, questionId, answer } = body as {
      quizSessionId: string;
      questionId: string;
      answer: string;
    };

    if (!quizSessionId || !questionId || !answer) {
      return NextResponse.json(
        { error: "Missing required fields" },
        { status: 400 },
      );
    }

    return handleAnswer(
      session.annotatorId,
      quizSessionId,
      questionId,
      answer,
    );
  }

  return NextResponse.json({ error: "Invalid action" }, { status: 400 });
}

async function handleStart(annotatorId: string) {
  const questions = drawQuizQuestions(8);
  const quizSessionId = crypto.randomUUID();

  await db.insert(quizSessions).values({
    id: quizSessionId,
    annotatorId,
    startedAt: new Date(),
    totalQuestions: 8,
    answers: "[]",
  });

  return NextResponse.json({ quizSessionId, questions });
}

async function handleAnswer(
  annotatorId: string,
  quizSessionId: string,
  questionId: string,
  answer: string,
) {
  const [quizSession] = await db
    .select()
    .from(quizSessions)
    .where(eq(quizSessions.id, quizSessionId))
    .limit(1);

  if (!quizSession) {
    return NextResponse.json(
      { error: "Quiz session not found" },
      { status: 404 },
    );
  }

  if (quizSession.annotatorId !== annotatorId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 403 });
  }

  if (quizSession.completedAt) {
    return NextResponse.json(
      { error: "Quiz already completed" },
      { status: 400 },
    );
  }

  const elapsed = Date.now() - quizSession.startedAt.getTime();
  if (elapsed > QUIZ_EXPIRY_MS) {
    return NextResponse.json({ error: "Quiz session expired" }, { status: 400 });
  }

  const question = QUIZ_QUESTIONS.find(
    (q: QuizQuestion) => q.id === questionId,
  );
  if (!question) {
    return NextResponse.json({ error: "Question not found" }, { status: 404 });
  }

  const existingAnswers: StoredAnswer[] = JSON.parse(quizSession.answers);

  const alreadyAnswered = existingAnswers.some(
    (a) => a.questionId === questionId,
  );
  if (alreadyAnswered) {
    return NextResponse.json(
      { error: "Question already answered" },
      { status: 400 },
    );
  }

  const correct = answer === question.correctAnswer;

  const updatedAnswers: StoredAnswer[] = [
    ...existingAnswers,
    { questionId, answer, correct },
  ];

  const allAnswered = updatedAnswers.length >= quizSession.totalQuestions;

  if (allAnswered) {
    const score = updatedAnswers.filter((a) => a.correct).length;
    const passed = score >= 7;

    await db
      .update(quizSessions)
      .set({
        answers: JSON.stringify(updatedAnswers),
        completedAt: new Date(),
        score,
        passed,
      })
      .where(eq(quizSessions.id, quizSessionId));

    return NextResponse.json({
      correct,
      correctAnswer: question.correctAnswer,
      explanation: question.explanation,
      score,
      passed,
      completed: true,
    });
  }

  await db
    .update(quizSessions)
    .set({ answers: JSON.stringify(updatedAnswers) })
    .where(eq(quizSessions.id, quizSessionId));

  return NextResponse.json({
    correct,
    correctAnswer: question.correctAnswer,
    explanation: question.explanation,
    completed: false,
  });
}
