import { Request, Response } from "express";
import { v4 as uuidv4 } from "uuid";
import InterviewQuizAssignment from "../models/interviewQuizAssignment";
import Quiz from "../models/quiz";
import { sendResponse, handleError } from "../utils/apiResponse";
import { toKolkataTime } from "../utils/timezone";
import { sendInterviewQuizEmail } from "../utils/emailService";

// Show interview quiz details before starting (no auth)
export const getInterviewQuizDetailsByToken = async (
  req: Request,
  res: Response,
) => {
  try {
    const { token } = req.params;
    const assignment = await InterviewQuizAssignment.findOne({
      token,
    }).populate({
      path: "quiz",
      select: "title questions start_datetime end_datetime",
      populate: {
        path: "questions",
        select: "_id",
      },
    });
    if (!assignment || !assignment.quiz) {
      sendResponse(res, 404, "Invalid or expired quiz link");
      return;
    }
    const quiz: any = assignment.quiz;
    const numQuestions = quiz.questions?.length || 0;
    // Example: 5 seconds per question (should match your logic)
    const durationSeconds = 5 * numQuestions;
    sendResponse(res, 200, "Quiz details fetched", {
      title: quiz.title,
      numQuestions,
      durationSeconds,
      start_datetime: quiz.start_datetime,
      end_datetime: quiz.end_datetime,
      candidateEmail: assignment.candidateEmail,
    });
  } catch (error) {
    handleError(res, error);
  }
};

// Admin creates and sends a unique quiz link to a candidate
export const createInterviewQuizAssignment = async (
  req: Request,
  res: Response,
) => {
  try {
    const { quizId, candidateEmail } = req.body;
    if (!quizId || !candidateEmail) {
      sendResponse(res, 400, "quizId and candidateEmail are required");
      return;
    }
    const quiz = await Quiz.findById(quizId);
    if (!quiz) {
      sendResponse(res, 404, "Quiz not found");
      return;
    }
    // Generate a unique secure token
    const token = uuidv4();
    const assignment = await InterviewQuizAssignment.create({
      quiz: quizId,
      candidateEmail,
      token,
      status: "pending",
    });
    // Construct the unique quiz link (adjust base URL as needed)
    const quizLink = `${process.env.INTERVIEW_BASE_URL || "http://localhost:5173"}/interview/quiz/attempt/${token}`;
    // Send quizLink to candidate via email
    try {
      await sendInterviewQuizEmail(candidateEmail, quizLink);
    } catch (emailError) {
      // Optionally log or handle email sending errors
      console.error("Failed to send interview quiz email:", emailError);
    }
    sendResponse(
      res,
      201,
      "Interview quiz assignment created and link sent to candidate",
      { assignment, quizLink },
    );
  } catch (error) {
    handleError(res, error);
  }
};

// Candidate starts quiz via secure token
export const startInterviewQuizByToken = async (
  req: Request,
  res: Response,
) => {
  try {
    const { token } = req.params;
    const assignment = await InterviewQuizAssignment.findOne({
      token,
    }).populate({
      path: "quiz",
      select: "questions title",
      populate: {
        path: "questions",
        select: "question_text option_a option_b option_c option_d points",
      },
    });
    if (!assignment) {
      sendResponse(res, 404, "Invalid or expired quiz link");
      return;
    }
    // Ensure quiz is populated
    const quiz: any =
      assignment.quiz &&
      typeof assignment.quiz === "object" &&
      "questions" in assignment.quiz
        ? assignment.quiz
        : null;
    if (!quiz) {
      sendResponse(res, 404, "Quiz not found");
      return;
    }
    if (assignment.status === "submitted" || assignment.status === "expired") {
      sendResponse(
        res,
        400,
        "This quiz attempt is already completed or expired",
      );
      return;
    }
    // If not started, set startedAt and expiresAt
    if (!assignment.startedAt) {
      const now = new Date();
      // Example: 5 seconds per question
      const durationSeconds = 5 * (quiz.questions?.length || 1);
      assignment.startedAt = now;
      assignment.expiresAt = new Date(now.getTime() + durationSeconds * 1000);
      assignment.status = "started";
      await assignment.save();
    }
    sendResponse(res, 200, "Quiz loaded", {
      quiz: assignment.quiz,
      startedAt: toKolkataTime(assignment.startedAt ?? new Date()),
      expiresAt: toKolkataTime(assignment.expiresAt ?? new Date()),
      status: assignment.status,
    });
  } catch (error) {
    handleError(res, error);
  }
};

// Candidate submits interview quiz answers via token
export const submitInterviewQuizByToken = async (
  req: Request,
  res: Response,
) => {
  try {
    const { token } = req.params;
    const { answers } = req.body as {
      answers?: { question_id: string; selected_option: string }[];
    };
    const assignment = await InterviewQuizAssignment.findOne({
      token,
    }).populate({ path: "quiz", select: "questions" });
    if (!assignment) {
      sendResponse(res, 404, "Invalid or expired quiz link");
      return;
    }
    if (assignment.status === "submitted" || assignment.status === "expired") {
      sendResponse(
        res,
        400,
        "This quiz attempt is already completed or expired",
      );
      return;
    }
    const now = new Date();
    if (!assignment.startedAt || !assignment.expiresAt) {
      sendResponse(res, 400, "Quiz not started properly");
      return;
    }
    // Allow a 3-second grace period for auto-submit
    const GRACE_SECONDS = 3;
    if (now.getTime() > assignment.expiresAt.getTime() + GRACE_SECONDS * 1000) {
      assignment.status = "expired";
      await assignment.save();
      sendResponse(res, 400, "Time is up! This quiz attempt has expired");
      return;
    }
    // Score answers (partial allowed)
    const quiz: any =
      assignment.quiz &&
      typeof assignment.quiz === "object" &&
      "questions" in assignment.quiz
        ? assignment.quiz
        : null;
    if (!quiz) {
      sendResponse(res, 404, "Quiz not found");
      return;
    }
    // Fetch correct answers
    const questionIds = quiz.questions.map((q: any) => q.toString());
    // Optionally: fetch question docs for correct_option
    // For now, just store answers as submitted
    assignment.status = "submitted";
    assignment.submittedAt = now;
    assignment.meta = { answers };
    await assignment.save();
    sendResponse(res, 201, "Quiz submitted successfully", {
      submittedAt: assignment.submittedAt,
    });
  } catch (error) {
    handleError(res, error);
  }
};
