import { Request, Response, NextFunction } from "express"
import { ShopUserRole } from "@prisma/client"
import { prisma } from "@/core/prisma"
import { AppError } from "@/core/AppError"

async function resolvePosRole(req: Request): Promise<ShopUserRole> {
    if (!req.auth || req.auth.type !== "pos") {
        throw new AppError("Forbidden", 403)
    }

    const cachedRole = (req as any).posRole as ShopUserRole | undefined
    if (cachedRole) {
        return cachedRole
    }

    const shopUser = await prisma.shopUser.findUnique({
        where: { id: req.auth.sub },
        select: {
            role: true,
            shopId: true,
            active: true
        }
    })

    if (!shopUser || !shopUser.active) {
        throw new AppError("Forbidden", 403)
    }

    if (req.shop && shopUser.shopId !== req.shop.id) {
        throw new AppError("Forbidden", 403)
    }

    ;(req as any).posRole = shopUser.role
    return shopUser.role
}

export const requirePosRoles =
    (...allowedRoles: ShopUserRole[]) =>
        async (req: Request, _res: Response, next: NextFunction) => {
            try {
                const role = await resolvePosRole(req)
                if (!allowedRoles.includes(role)) {
                    throw new AppError("Forbidden", 403)
                }
                next()
            } catch (error) {
                next(error)
            }
        }

export const requireAdminOrPosRoles =
    (...allowedRoles: ShopUserRole[]) =>
        async (req: Request, _res: Response, next: NextFunction) => {
            try {
                if (req.auth?.type === "admin") {
                    return next()
                }

                const role = await resolvePosRole(req)
                if (!allowedRoles.includes(role)) {
                    throw new AppError("Forbidden", 403)
                }

                next()
            } catch (error) {
                next(error)
            }
        }
