// Role Management Service
// Role definitions, access control

import prisma from '@/shared/database/prisma';
import { v4 as uuidv4 } from 'uuid';
import { rbacEngineService } from './permissions/rbac-engine.service';
import {
  Action,
  ScreenName,
  PermissionCheckResult,
  ScreenVisibilityResult,
  ParticipantType,
} from './permissions/permission-types';

export interface RoleData {
  roleName: string;
  roleDescription: string;
  accessLevel: string;
  permissions: string[];
}

export class RoleManagementService {
  /**
   * Initialize default DBIS roles
   */
  async initializeDefaultRoles() {
    const defaultRoles: RoleData[] = [
      {
        roleName: 'Governor',
        roleDescription: 'DBIS Governor - Supreme authority',
        accessLevel: 'tier_1',
        permissions: ['all'],
      },
      {
        roleName: 'MSC_Officer',
        roleDescription: 'Monetary & Settlement Council Officer',
        accessLevel: 'tier_2',
        permissions: ['fx_governance', 'liquidity_management', 'settlement_finality'],
      },
      {
        roleName: 'CAA_Auditor',
        roleDescription: 'Compliance & Audit Authority Auditor',
        accessLevel: 'tier_2',
        permissions: ['compliance_audit', 'aml_supervision', 'sanctions_screening'],
      },
      {
        roleName: 'Sovereign_Relations_Director',
        roleDescription: 'Sovereign Relations Director',
        accessLevel: 'tier_3',
        permissions: ['sovereign_relations', 'dispute_mediation'],
      },
      {
        roleName: 'Crisis_Operations_Commander',
        roleDescription: 'Crisis Operations Commander',
        accessLevel: 'tier_1',
        permissions: ['crisis_activation', 'emergency_liquidity', 'settlement_restrictions'],
      },
      // Admin Console Roles
      {
        roleName: 'DBIS_Super_Admin',
        roleDescription: 'DBIS Super Admin - Full network control',
        accessLevel: 'tier_1',
        permissions: ['all'],
      },
      {
        roleName: 'DBIS_Ops',
        roleDescription: 'DBIS Operations - Network monitoring and operations',
        accessLevel: 'tier_2',
        permissions: ['network_operations', 'gas_qps_control', 'incident_management'],
      },
      {
        roleName: 'DBIS_Risk',
        roleDescription: 'DBIS Risk Officer - Risk monitoring and compliance',
        accessLevel: 'tier_2',
        permissions: ['risk_monitoring', 'compliance_audit', 'stress_testing'],
      },
      {
        roleName: 'SCB_Admin',
        roleDescription: 'SCB Admin - Full control over jurisdiction',
        accessLevel: 'tier_3',
        permissions: ['scb_administration', 'fi_management', 'corridor_management'],
      },
      {
        roleName: 'SCB_Risk',
        roleDescription: 'SCB Risk Officer - Local risk monitoring',
        accessLevel: 'tier_3',
        permissions: ['local_risk_monitoring', 'compliance_review'],
      },
      {
        roleName: 'SCB_Tech',
        roleDescription: 'SCB Tech/API Owner - Technical operations',
        accessLevel: 'tier_3',
        permissions: ['api_management', 'technical_operations'],
      },
      {
        roleName: 'SCB_Read_Only',
        roleDescription: 'SCB Read-Only - View-only access',
        accessLevel: 'tier_4',
        permissions: ['view_only'],
      },
    ];

    for (const roleData of defaultRoles) {
      const existing = await prisma.dbisRole.findFirst({
        where: { roleName: roleData.roleName },
      });

      if (!existing) {
        await prisma.dbisRole.create({
          data: {
            id: uuidv4(),
            roleId: uuidv4(),
            roleName: roleData.roleName,
            roleDescription: roleData.roleDescription,
            accessLevel: roleData.accessLevel,
            permissions: roleData.permissions,
            status: 'active',
          },
        });
      }
    }
  }

  /**
   * Create role
   */
  async createRole(roleData: RoleData) {
    return await prisma.dbisRole.create({
      data: {
        id: uuidv4(),
        roleId: uuidv4(),
        roleName: roleData.roleName,
        roleDescription: roleData.roleDescription,
        accessLevel: roleData.accessLevel,
        permissions: roleData.permissions,
        status: 'active',
      },
    });
  }

  /**
   * Get role by ID
   */
  async getRole(roleId: string) {
    return await prisma.dbisRole.findUnique({
      where: { roleId },
      include: { employees: true },
    });
  }

  /**
   * Get all roles
   */
  async getAllRoles() {
    return await prisma.dbisRole.findMany({
      where: { status: 'active' },
      include: {
        employees: {
          where: { status: 'active' },
        },
      },
    });
  }

  /**
   * Update role
   */
  async updateRole(roleId: string, updates: Partial<RoleData>) {
    return await prisma.dbisRole.update({
      where: { roleId },
      data: {
        roleName: updates.roleName,
        roleDescription: updates.roleDescription,
        accessLevel: updates.accessLevel,
        permissions: updates.permissions,
      },
    });
  }

  /**
   * Check if user has permission
   */
  async hasPermission(employeeId: string, permission: string): Promise<boolean> {
    const employee = await prisma.employeeCredential.findUnique({
      where: { employeeId },
      include: { role: true },
    });

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

    const permissions = employee.role.permissions as string[];
    return permissions.includes('all') || permissions.includes(permission);
  }

  /**
   * Get access level for employee
   */
  async getAccessLevel(employeeId: string): Promise<string | null> {
    const employee = await prisma.employeeCredential.findUnique({
      where: { employeeId },
      include: { role: true },
    });

    return employee?.role.accessLevel || null;
  }

  /**
   * Check permission using RBAC engine (new method)
   */
  async checkPermission(
    employeeId: string,
    module: string,
    action: Action,
    context?: { amount?: number; currency?: string; metadata?: Record<string, unknown> }
  ): Promise<PermissionCheckResult> {
    return await rbacEngineService.checkPermission(employeeId, module, action, {
      resourceType: module,
      amount: context?.amount,
      currency: context?.currency,
      metadata: context?.metadata,
    });
  }

  /**
   * Check screen access using RBAC engine (new method)
   */
  async checkScreenAccess(
    employeeId: string,
    screenName: ScreenName
  ): Promise<ScreenVisibilityResult> {
    return await rbacEngineService.checkScreenAccess(employeeId, screenName);
  }

  /**
   * Get all accessible screens for employee (new method)
   */
  async getAccessibleScreens(employeeId: string): Promise<ScreenName[]> {
    return await rbacEngineService.getAccessibleScreens(employeeId);
  }

  /**
   * Get all allowed actions for a module (new method)
   */
  async getAllowedActions(employeeId: string, module: string): Promise<Action[]> {
    return await rbacEngineService.getAllowedActions(employeeId, module);
  }

  /**
   * Get role definition from RBAC schema (new method)
   */
  async getRoleDefinition(
    employeeId: string
  ): Promise<{
    roleName: string;
    participant: ParticipantType;
    accessLevel: string;
    description: string;
  } | null> {
    const employee = await prisma.employeeCredential.findUnique({
      where: { employeeId },
      include: { role: true },
    });

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

    const roleName = employee.role.roleName;
    let participant: ParticipantType = 'DBIS';

    if (roleName.startsWith('SCB_')) {
      participant = 'SCB';
    } else if (roleName.startsWith('FI_')) {
      participant = 'FI';
    }

    const roleDef = rbacEngineService.getRoleDefinitionForRole(participant, roleName);
    if (!roleDef) {
      return null;
    }

    return {
      roleName,
      participant,
      accessLevel: employee.role.accessLevel,
      description: roleDef.description,
    };
  }
}

export const roleManagementService = new RoleManagementService();

