import type { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';
import type { Role } from '../interface/types.ts';
import { prisma } from '../config/db.ts';

export async function protect(req: Request, res: Response, next: NextFunction) {
    const auth = req.headers.authorization;

    if (!auth || !auth.startsWith('Bearer ')) {
        return res.status(401).json({ message: 'Not authorized' });
    }

    const token = auth.split(' ')[1];

    try {
        const payload: any = jwt.verify(token, process.env.JWT_SECRET as string);

        // Fetch user
        const user = await prisma.user.findUnique({ where: { id: payload.id, isDeleted: false } });
        // TEMPORARY: Commented out single-device session enforcement
        if (!user /* || user.sessionToken !== payload.sessionToken */) {
            return res.status(401).json({ message: "User not found or session expired" });
        }

        req.user = {
            ...user,
            institutionId: payload.institutionId
        };

        // Role-based check

        if (user.role === "STAFF") {
            const staff = await prisma.staff.findUnique({ where: { userId: user.id } });
            if (!staff) {
                return res.status(401).json({ message: "Staff not found" });
            }
        }

        if (user.role === "STUDENT") {
            const student = await prisma.student.findUnique({ where: { userId: user.id } });
            if (!student) {
                res.status(401).json({ message: "Student not found" });
                return
            }
            // x-institution-id header overrides JWT's institutionId
            const headerStudentInstId = req.headers['x-student-institution-id'] as string | undefined;
            if (!headerStudentInstId || !req.user) return res.status(401).json({ message: "institutionId not found in the request" });;
            console.log(12)

            const studentInstitution = await prisma.studentInstitution.findUnique({
                where: { id: headerStudentInstId, deletedAt: null, },
                select: { institutionId: true }
            });

            if (!studentInstitution || !studentInstitution.institutionId) {
                res.status(401).json({ message: "Student institution not found" });
                return
            }
            req.user.studentInstitutionId = headerStudentInstId;
            req.user.institutionId = studentInstitution.institutionId;
        }


        next();

    } catch (err) {
        return res.status(401).json({ message: 'Invalid or expired token' });
    }
}

export function permit(...allowed: Role[]) {
    return (req: Request, res: Response, next: NextFunction) => { 
        if (!req.user) return res.status(401).json({ message: 'Not authorized' });
        let allowedRoles = allowed.map((role) => role.toUpperCase());
        if (!allowedRoles.includes(req.user.role.toUpperCase())) return res.status(403).json({ message: 'Forbidden' });
        next();
    };
}

export function onlyAdmin(req: Request, res: Response, next: NextFunction) {
    if ((req as any).user.role !== "ADMIN") {
        res.status(403).json({ message: "Admin only route" });
        return;
    }
    next();
}