import type { Request, Response } from "express";
import { prisma } from "../config/db.ts";
import { toIST } from "../utils/time.ts";
import asyncHandler from "express-async-handler";

// Create Exam
export const createExam = asyncHandler(async (req: Request, res: Response) => {
    const { examName, isPublished } = req.body;
    const user = (req as any).user;

    if (!examName) {
        res.status(400).json({ message: "examName is required" });
        return;
    }

    const existing = await prisma.exam.findFirst({
        where: { institutionId: user.institutionId, examName: { equals: examName } }
    });

    if (existing) {
        res.status(400).json({ message: "examName already exists" });
        return;
    }

    const exam = await prisma.exam.create({
        data: {
            examName,
            institutionId: user.institutionId,
            isPublished: typeof isPublished === "boolean" ? isPublished : undefined
        }
    });

    res.status(201).json({
        message: "Exam created",
        data: {
            ...exam,
            createdAt: toIST(exam.createdAt),
            updatedAt: toIST(exam.updatedAt),
        }
    });
});

// Get all Exams
export const getExams = asyncHandler(async (req: Request, res: Response) => {
    const search = (req.query.search as string) || "";
    const page = Number(req.query.page || 1);
    const limit = Number(req.query.limit || 10);
    const skip = (page - 1) * limit;

    const user = (req as any).user;
    let institutionId = user.role === "ADMIN" && req.query.institutionId
        ? (req.query.institutionId as string)
        : user.institutionId;

    if (user.role === "ADMIN" && req.query.institutionId) {
        const instRec = await prisma.institution.findFirst({
            where: { userId: req.query.institutionId as string },
            select: { id: true }
        });
        if (instRec) {
            institutionId = instRec.id;
        }
    }

    const where: any = {
        institutionId: institutionId,
        examName: { contains: search },
    };

    if (user.role === "STUDENT") {
        where.isPublished = true;
    } else if (req.query.isPublished !== undefined) {
        where.isPublished = req.query.isPublished === "true";
    }

    const [total, exams] = await Promise.all([
        prisma.exam.count({ where }),
        prisma.exam.findMany({
            where,
            include: {
                institution: {
                    include: { user: { select: { institutionName: true } } }
                },
                _count: {
                    select: {
                        practiceTests: { where: { institutionId: institutionId } },
                        mockTests: { where: { institutionId: institutionId } }
                    }
                }
            },
            orderBy: { examName: 'asc' },
            skip,
            take: limit,
        }),
    ]);

    const updatedExams = exams.map((exam) => {
        const { _count, institutionId: examInstId, institution, ...rest } = exam;

        let examName = exam.examName;
        let sharedFromName = null;
        if (examInstId && examInstId !== institutionId) {
            sharedFromName = institution?.user?.institutionName || "another institution";
            examName = `${exam.examName} (shared from ${sharedFromName})`;
        }

        return user.role === "STUDENT" ? {
            id: exam.id,
            examName: examName,
            baseExamName: exam.examName,
            sharedFromName: sharedFromName,
            isPublished: exam.isPublished
        } : {
            ...rest,
            examName: examName,
            baseExamName: exam.examName,
            sharedFromName: sharedFromName,
            createdAt: toIST(exam.createdAt),
            updatedAt: toIST(exam.updatedAt),
            testCount: _count.practiceTests,
            mockTestCount: _count.mockTests,
        };
    });

    res.status(200).json({
        data: updatedExams,
        meta: {
            total,
            page,
            limit,
            totalPages: Math.ceil(total / limit),
        }
    });
});

// Update Exam
export const updateExam = asyncHandler(async (req: Request, res: Response) => {
    const user = (req as any).user;
    const { id } = req.params;
    const { examName, isPublished } = req.body;

    const updateData: any = {};

    if (!examName || examName.trim() === "") {
        res.status(400).json({ message: "No valid fields to update" });
        return;
    }

    updateData.examName = examName;

    if (typeof isPublished === "boolean") {
        updateData.isPublished = isPublished;
    }

    if (Object.keys(updateData).length === 0) {
        res.status(400).json({ message: "No valid fields to update" });
        return;
    }

    const updated = await prisma.exam.update({
        where: { id, institutionId: user.institutionId },
        data: updateData
    });

    res.status(200).json({
        message: "Exam updated successfully",
        data: {
            ...updated,
            createdAt: toIST(updated.createdAt),
            updatedAt: toIST(updated.updatedAt),
        },
    });
});

// Delete Exam
export const deleteExam = asyncHandler(async (req: Request, res: Response) => {
    const user = (req as any).user;
    const { id } = req.params;

    const exam = await prisma.exam.findUnique({ 
        where: { id, institutionId: user.institutionId },
        include: {
            _count: {
                select: {
                    practiceTests: true,
                    mockTests: true,
                    oldQuestionPapers: true
                }
            }
        }
    });

    if (!exam) {
        res.status(404).json({ message: "Exam not found" });
        return;
    }

    if (exam._count.practiceTests > 0) {
        res.status(400).json({ message: "Exam cannot be deleted as it has Practice Tests" });
        return;
    }

    if (exam._count.mockTests > 0) {
        res.status(400).json({ message: "Exam cannot be deleted as it has Mock Tests" });
        return;
    }

    if (exam._count.oldQuestionPapers > 0) {
        res.status(400).json({ message: "Exam cannot be deleted as it has PYQ (Previous Question Papers)" });
        return;
    }

    await prisma.exam.delete({
        where: { id, institutionId: user.institutionId }
    });

    res.status(201).json({ message: "Exam deleted successfully" });
});