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

export const createRole = asyncHandler(async (req: Request, res: Response) => {
    const user = req.user;
    const { roleName, permissions } = req.body;

    if (!roleName || !permissions) {
        res.status(400).json({ message: "Missing fields" });
        return;
    }

    const where: any = {
        institutionId: user.institutionId,
        roleName,
    };

    const existingRole = await prisma.role.findFirst({ where });
    if (existingRole) {
        res.status(400).json({ message: "Role already exists" });
        return;
    }

    const role = await prisma.role.create({
        data: {
            roleName,
            permissions: Array.isArray(permissions) ? permissions : [],
            createdById: user.id,
            institutionId: user.institutionId,
        },
    });

    res.status(201).json({
        message: "Role created successfully",
        data: {
            ...role,
            createdAt: toIST(role.createdAt),
            updatedAt: toIST(role.updatedAt),
        },
    });
});

export const listRoles = asyncHandler(async (req: Request, res: Response) => {
    const user = (req as any).user;
    const search = (req.query.search as string)?.trim() || "";
    const page = Math.max(parseInt(req.query.page as string) || 1, 1);
    const limit = Math.max(parseInt(req.query.limit as string) || 10, 1);
    const skip = (page - 1) * limit;

    const where: any = {
        institutionId: user.institutionId,
    };

    if (search) {
        where.roleName = { contains: search };
    }

    const [total, roles] = await Promise.all([
        prisma.role.count({ where }),
        prisma.role.findMany({
            where,
            orderBy: { roleName: 'asc' },
            skip,
            take: limit,
        }),
    ]);

    res.status(200).json({
        message: "Successfully fetched roles list.",
        data: roles.map((role: any) => ({
            ...role,
            createdAt: toIST(role.createdAt),
            updatedAt: toIST(role.updatedAt),
        })),
        meta: {
            total,
            page,
            limit,
            totalPages: Math.ceil(total / limit),
        },
    });
});

export const updateRole = asyncHandler(async (req: Request, res: Response) => {
    const roleId = req.params.id;
    const { roleName, permissions } = req.body;
    const user = (req as any).user;

    try {
        const role = await prisma.role.update({
            where: { id: roleId, institutionId: user.institutionId },
            data: {
                roleName,
                permissions: Array.isArray(permissions) ? permissions : (permissions ? [permissions] : undefined)
            }
        });

        res.status(200).json({
            message: "Role updated successfully",
            data: {
                ...role,
                createdAt: toIST(role.createdAt),
                updatedAt: toIST(role.updatedAt),
            },
        });
    } catch (error) {
        res.status(404).json({ message: "Role not found" });
    }
});

export const deleteRole = asyncHandler(async (req: Request, res: Response) => {
    const roleId = req.params.id;
    const user = (req as any).user;

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

    // Check if role exists
    const role = await prisma.role.findFirst({
        where: { id: roleId, institutionId: user.institutionId },
    });

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

    // Check if any staff is using this role
    const staffCount = await prisma.staff.count({
        where: { roleId },
    });

    if (staffCount > 0) {
        res.status(400).json({ message: "Role is in use and cannot be deleted" });
        return;
    }

    // Delete role
    await prisma.role.delete({
        where: { id: roleId },
    });

    res.status(200).json({
        message: "Role deleted successfully",
        deletedRoleId: roleId,
    });
});
