﻿import {
  CanActivate,
  ExecutionContext,
  ForbiddenException,
  Injectable,
} from "@nestjs/common";
import { UserRole } from "../entities/usuario.entity";
import { PERMISSION_METADATA_KEY } from "../decorators/require-permission.decorator";

type PermissionMap = Record<string, "none" | "read" | "write">;

const DEFAULT_PERMISSIONS_BY_ROLE: Record<string, PermissionMap> = {
  [UserRole.SUPER_ADMIN]: {
    usuarios: "write",
    clientes: "write",
    vehiculos: "write",
    ots: "write",
    catalogos: "write",
    productos: "write",
    historial: "write",
    sync: "write",
    uploads: "write",
    cotizaciones: "write",
    reportes: "write",
  },
  [UserRole.ADMIN]: {
    usuarios: "read",
    clientes: "write",
    vehiculos: "write",
    ots: "write",
    catalogos: "write",
    productos: "write",
    historial: "read",
    sync: "write",
    uploads: "write",
    cotizaciones: "write",
    reportes: "write",
  },
  [UserRole.OPERATIVO]: {
    usuarios: "none",
    clientes: "read",
    vehiculos: "read",
    ots: "write",
    catalogos: "read",
    productos: "read",
    historial: "read",
    sync: "write",
    uploads: "write",
    cotizaciones: "write",
    reportes: "read",
  },
  [UserRole.RECEPCION]: {
    usuarios: "none",
    clientes: "read",
    vehiculos: "read",
    ots: "write",
    catalogos: "read",
    productos: "read",
    historial: "read",
    sync: "write",
    uploads: "write",
    cotizaciones: "write",
    reportes: "read",
  },
  [UserRole.MECANICO]: {
    usuarios: "none",
    clientes: "read",
    vehiculos: "read",
    ots: "write",
    catalogos: "read",
    productos: "read",
    historial: "read",
    sync: "write",
    uploads: "write",
    cotizaciones: "write",
    reportes: "none",
  },
};

@Injectable()
export class PermissionGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const handler = context.getHandler();
    const controller = context.getClass();

    const requirement =
      Reflect.getMetadata(PERMISSION_METADATA_KEY, handler) ||
      Reflect.getMetadata(PERMISSION_METADATA_KEY, controller);

    if (!requirement) {
      return true;
    }

    const request = context.switchToHttp().getRequest();
    const user = request.user;

    if (!user) {
      throw new ForbiddenException("Usuario no autenticado");
    }

    if (user.rol === UserRole.SUPER_ADMIN) {
      return true;
    }

    const basePermissions: PermissionMap =
      DEFAULT_PERMISSIONS_BY_ROLE[user.rol] || {};
    const userPermissions: PermissionMap = {
      ...basePermissions,
      ...(user.permissions || {}),
    };

    const currentLevel = userPermissions[requirement.module] || "none";

    if (requirement.level === "read") {
      if (currentLevel === "read" || currentLevel === "write") {
        return true;
      }
      throw new ForbiddenException(
        `Sin permiso de lectura para módulo ${requirement.module}`,
      );
    }

    if (currentLevel === "write") {
      return true;
    }

    throw new ForbiddenException(
      `Sin permiso de escritura para módulo ${requirement.module}`,
    );
  }
}
