import { prisma } from "../../core/prisma"
import { AppError } from "../../core/AppError"
import {
    type ShopUserPermissionKey,
    type ShopUserPermissionOverrides,
    isEmptyShopUserPermissionOverrides,
    normalizeShopUserPermissionOverrides,
    resolveShopUserEffectivePermissions,
} from "ttm-shared"

export interface ShopUserPermissionContext {
    id: string
    shopId: string
    role: "MANAGER" | "CASHIER" | "STAFF" | "RUNNER"
    active: boolean
    stationIds: string[]
    permissionOverrides: ShopUserPermissionOverrides
    effectivePermissions: ShopUserPermissionKey[]
}

export function readShopUserPermissionOverrides(value: unknown): ShopUserPermissionOverrides {
    if (!value || typeof value !== "object" || Array.isArray(value)) {
        return normalizeShopUserPermissionOverrides(null)
    }

    return normalizeShopUserPermissionOverrides(value as Partial<ShopUserPermissionOverrides>)
}

export function serializeShopUserPermissionOverrides(value: unknown): ShopUserPermissionOverrides | null {
    const normalized = readShopUserPermissionOverrides(value)
    return isEmptyShopUserPermissionOverrides(normalized) ? null : normalized
}

export function buildShopUserPermissionSnapshot(user: {
    role: "MANAGER" | "CASHIER" | "STAFF" | "RUNNER"
    permissionOverrides?: unknown
}) {
    const permissionOverrides = readShopUserPermissionOverrides(user.permissionOverrides)
    const effectivePermissions = resolveShopUserEffectivePermissions(user.role, permissionOverrides)

    return {
        permissionOverrides,
        effectivePermissions,
    }
}

export async function getShopUserPermissionContext(shopId: string, shopUserId: string): Promise<ShopUserPermissionContext> {
    const shopUser = await prisma.shopUser.findFirst({
        where: {
            id: shopUserId,
            shopId,
        },
        select: {
            id: true,
            shopId: true,
            role: true,
            active: true,
            permissionOverrides: true,
            stations: {
                select: {
                    stationId: true,
                },
            },
        },
    })

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

    const { permissionOverrides, effectivePermissions } = buildShopUserPermissionSnapshot(shopUser)

    return {
        id: shopUser.id,
        shopId: shopUser.shopId,
        role: shopUser.role,
        active: shopUser.active,
        stationIds: shopUser.stations.map((station) => station.stationId),
        permissionOverrides,
        effectivePermissions,
    }
}

export function ensureShopUserHasPermission(
    context: ShopUserPermissionContext,
    permission: ShopUserPermissionKey,
    message = "Action non autorisée pour ce compte.",
) {
    if (!context.effectivePermissions.includes(permission)) {
        throw new AppError(message, 403)
    }
}

export function ensureShopUserCanAccessStation(
    context: ShopUserPermissionContext,
    stationId: string | null | undefined,
    message = "Cette station n'est pas attribuée à ce compte.",
) {
    if (!stationId) return
    if (context.role === "MANAGER") return

    if (!context.stationIds.includes(stationId)) {
        throw new AppError(message, 403)
    }
}
