// Admin Permissions Service
// Permission checking and role management for admin consoles

import { AdminPermission, AdminRole, ROLE_PERMISSIONS } from './permissions.constants';
import { roleManagementService } from '@/core/operations/role-management.service';
import { logger } from '@/infrastructure/monitoring/logger';

export interface PermissionCheckResult {
  allowed: boolean;
  reason?: string;
}

export class AdminPermissionsService {
  /**
   * Check if employee has specific permission
   */
  async hasPermission(
    employeeId: string,
    permission: AdminPermission
  ): Promise<boolean> {
    try {
      // First check if they have 'all' permission (DBIS Governor)
      const hasAll = await roleManagementService.hasPermission(employeeId, 'all');
      if (hasAll) {
        return true;
      }

      // Get employee's role
      const roleName = await this.getEmployeeRoleName(employeeId);
      if (!roleName) {
        return false;
      }

      // Map DBIS role names to AdminRole enum
      const adminRole = this.mapRoleToAdminRole(roleName);
      if (!adminRole) {
        return false;
      }

      // Check if role has permission
      const rolePermissions = ROLE_PERMISSIONS[adminRole] || [];
      return rolePermissions.includes(permission);
    } catch (error) {
      logger.error('Error checking permission', {
        employeeId,
        permission,
        error: error instanceof Error ? error.message : 'Unknown error',
      });
      return false;
    }
  }

  /**
   * Check permission with detailed result
   */
  async checkPermission(
    employeeId: string,
    permission: AdminPermission
  ): Promise<PermissionCheckResult> {
    const allowed = await this.hasPermission(employeeId, permission);
    return {
      allowed,
      reason: allowed ? undefined : 'Insufficient permissions',
    };
  }

  /**
   * Check if employee can perform action on specific SCB
   * SCB admins can only act on their own SCB
   */
  async canActOnSCB(
    employeeId: string,
    targetSCBId: string,
    employeeSCBId?: string
  ): Promise<boolean> {
    // DBIS admins can act on any SCB
    const hasAll = await roleManagementService.hasPermission(employeeId, 'all');
    if (hasAll) {
      return true;
    }

    // SCB admins can only act on their own SCB
    if (employeeSCBId && employeeSCBId === targetSCBId) {
      return true;
    }

    return false;
  }

  /**
   * Get all permissions for an employee
   */
  async getEmployeePermissions(employeeId: string): Promise<AdminPermission[]> {
    try {
      const hasAll = await roleManagementService.hasPermission(employeeId, 'all');
      if (hasAll) {
        // Return all permissions
        return Object.values(AdminPermission);
      }

      // Get employee to find their role
      const prisma = (await import('@/shared/database/prisma')).default;
      const employee = await prisma.employee_credentials.findUnique({
        where: { employeeId },
        include: { dbis_roles: true },
      });

      if (!employee || employee.status !== 'active') {
        return [];
      }

      const adminRole = this.mapRoleToAdminRole(employee.dbis_roles?.roleName || '');
      if (!adminRole) {
        return [];
      }

      return ROLE_PERMISSIONS[adminRole] || [];
    } catch (error) {
      logger.error('Error getting employee permissions', {
        employeeId,
        error: error instanceof Error ? error.message : 'Unknown error',
      });
      return [];
    }
  }

  /**
   * Get employee's role name
   */
  async getEmployeeRoleName(employeeId: string): Promise<string | null> {
    try {
      const prisma = (await import('@/shared/database/prisma')).default;
      const employee = await prisma.employee_credentials.findUnique({
        where: { employeeId },
        include: { dbis_roles: true },
      });

      return employee?.dbis_roles?.roleName || null;
    } catch (error) {
      logger.error('Error getting employee role', {
        employeeId,
        error: error instanceof Error ? error.message : 'Unknown error',
      });
      return null;
    }
  }

  /**
   * Map DBIS role name to AdminRole enum
   */
  private mapRoleToAdminRole(roleName: string): AdminRole | null {
    const roleMap: Record<string, AdminRole> = {
      Governor: AdminRole.DBIS_SUPER_ADMIN,
      MSC_Officer: AdminRole.DBIS_OPS,
      CAA_Auditor: AdminRole.DBIS_RISK,
      DBIS_Super_Admin: AdminRole.DBIS_SUPER_ADMIN,
      DBIS_Ops: AdminRole.DBIS_OPS,
      DBIS_Risk: AdminRole.DBIS_RISK,
      SCB_Admin: AdminRole.SCB_ADMIN,
      SCB_Risk: AdminRole.SCB_RISK,
      SCB_Tech: AdminRole.SCB_TECH,
      SCB_Read_Only: AdminRole.SCB_READ_ONLY,
    };

    return roleMap[roleName] || null;
  }

  /**
   * Check if role is DBIS-level (can act globally)
   */
  async isDBISLevel(employeeId: string): Promise<boolean> {
    const hasAll = await roleManagementService.hasPermission(employeeId, 'all');
    if (hasAll) {
      return true;
    }

      const roleName = await this.getEmployeeRoleName(employeeId);
      if (!roleName) {
        return false;
      }

      const adminRole = this.mapRoleToAdminRole(roleName);
    return (
      adminRole === AdminRole.DBIS_SUPER_ADMIN ||
      adminRole === AdminRole.DBIS_OPS ||
      adminRole === AdminRole.DBIS_RISK
    );
  }
}

export const adminPermissionsService = new AdminPermissionsService();

