// Crisis Management Service
// Escalation workflows, crisis activation

import prisma from '@/shared/database/prisma';
import { v4 as uuidv4 } from 'uuid';


export interface CrisisProtocolData {
  protocolName: string;
  crisisType: string;
  escalationChain: Array<{
    level: number;
    role: string;
    action: string;
    timeout: number; // minutes
  }>;
  activationCriteria: Record<string, unknown>;
}

export class CrisisManagementService {
  /**
   * Initialize default crisis protocols
   */
  async initializeDefaultProtocols() {
    const protocols: CrisisProtocolData[] = [
      {
        protocolName: 'FX Collapse Protocol',
        crisisType: 'fx_collapse',
        escalationChain: [
          {
            level: 1,
            role: 'MSC_Officer',
            action: 'Assess FX market conditions',
            timeout: 15,
          },
          {
            level: 2,
            role: 'Crisis_Operations_Commander',
            action: 'Activate FX stabilization measures',
            timeout: 30,
          },
          {
            level: 3,
            role: 'Governor',
            action: 'Emergency FX intervention',
            timeout: 60,
          },
        ],
        activationCriteria: {
          fxVolatility: 0.15, // 15% volatility
          duration: 3600, // 1 hour
        },
      },
      {
        protocolName: 'Default Event Protocol',
        crisisType: 'default_event',
        escalationChain: [
          {
            level: 1,
            role: 'CAA_Auditor',
            action: 'Assess default severity',
            timeout: 30,
          },
          {
            level: 2,
            role: 'Crisis_Operations_Commander',
            action: 'Activate default resolution procedures',
            timeout: 60,
          },
          {
            level: 3,
            role: 'Governor',
            action: 'Emergency liquidity injection',
            timeout: 120,
          },
        ],
        activationCriteria: {
          sriScore: 60,
          defaultType: ['liquidity_default', 'reserve_breach'],
        },
      },
      {
        protocolName: 'Liquidity Freeze Protocol',
        crisisType: 'liquidity_freeze',
        escalationChain: [
          {
            level: 1,
            role: 'MSC_Officer',
            action: 'Assess liquidity conditions',
            timeout: 15,
          },
          {
            level: 2,
            role: 'Crisis_Operations_Commander',
            action: 'Activate emergency liquidity facilities',
            timeout: 30,
          },
          {
            level: 3,
            role: 'Governor',
            action: 'Mandatory liquidity injection',
            timeout: 60,
          },
        ],
        activationCriteria: {
          lcr: 0.8, // LCR below 80%
          nsfr: 0.8, // NSFR below 80%
        },
      },
    ];

    for (const protocolData of protocols) {
      const existing = await prisma.crisisProtocol.findFirst({
        where: {
          crisisType: protocolData.crisisType,
          status: 'active',
        },
      });

      if (!existing) {
        await prisma.crisisProtocol.create({
          data: {
            id: uuidv4(),
            protocolId: uuidv4(),
            protocolName: protocolData.protocolName,
            crisisType: protocolData.crisisType,
            escalationChain: protocolData.escalationChain,
            activationCriteria: protocolData.activationCriteria,
            status: 'active',
            effectiveDate: new Date(),
          },
        });
      }
    }
  }

  /**
   * Activate crisis protocol
   */
  async activateCrisisProtocol(crisisType: string, context: Record<string, unknown>) {
    const protocol = await prisma.crisisProtocol.findFirst({
      where: {
        crisisType,
        status: 'active',
      },
    });

    if (!protocol) {
      throw new Error(`Crisis protocol not found for type: ${crisisType}`);
    }

    // Check activation criteria
    const shouldActivate = this.checkActivationCriteria(protocol.activationCriteria, context);
    if (!shouldActivate) {
      return {
        activated: false,
        reason: 'Activation criteria not met',
      };
    }

    // Activate protocol
    await prisma.crisisProtocol.update({
      where: { id: protocol.id },
      data: {
        activatedAt: new Date(),
      },
    });

    // Start escalation chain
    const escalationChain = protocol.escalationChain as Array<{
      level: number;
      role: string;
      action: string;
      timeout: number;
    }>;

    // Execute first level
    await this.executeEscalationLevel(protocol.id, escalationChain[0], context);

    return {
      activated: true,
      protocolId: protocol.protocolId,
      escalationLevel: 1,
    };
  }

  /**
   * Execute escalation level
   */
  private async executeEscalationLevel(
    protocolId: string,
    level: { level: number; role: string; action: string; timeout: number },
    context: Record<string, unknown>
  ) {
    // Find employees with the required role
    const role = await prisma.dbisRole.findFirst({
      where: { roleName: level.role },
    });

    if (!role) {
      throw new Error(`Role not found: ${level.role}`);
    }

    const employees = await prisma.employeeCredential.findMany({
      where: {
        roleId: role.id,
        status: 'active',
      },
    });

    // Notify employees (in production, would send notifications)
    for (const employee of employees) {
      await prisma.auditLog.create({
        data: {
          eventType: 'crisis_escalation',
          entityType: 'crisis_protocol',
          entityId: protocolId,
          action: level.action,
          actorId: employee.employeeId,
          actorType: 'employee',
          details: {
            level: level.level,
            role: level.role,
            timeout: level.timeout,
            context,
          },
        },
      });
    }
  }

  /**
   * Check activation criteria
   */
  private checkActivationCriteria(
    criteria: Record<string, unknown>,
    context: Record<string, unknown>
  ): boolean {
    for (const [key, value] of Object.entries(criteria)) {
      const contextValue = context[key];

      if (typeof value === 'number' && typeof contextValue === 'number') {
        // For thresholds, check if context value exceeds threshold
        if (key.includes('Volatility') || key.includes('Score')) {
          if (contextValue < value) {
            return false;
          }
        } else {
          if (contextValue > value) {
            return false;
          }
        }
      } else if (Array.isArray(value)) {
        // For arrays, check if context value is in array
        if (!value.includes(contextValue)) {
          return false;
        }
      } else {
        // Exact match
        if (contextValue !== value) {
          return false;
        }
      }
    }

    return true;
  }

  /**
   * Resolve crisis
   */
  async resolveCrisis(protocolId: string, resolution: string) {
    return await prisma.crisisProtocol.update({
      where: { protocolId },
      data: {
        resolvedAt: new Date(),
      },
    });
  }

  /**
   * Get active crises
   */
  async getActiveCrises() {
    return await prisma.crisisProtocol.findMany({
      where: {
        status: 'active',
        activatedAt: {
          not: null,
        },
        resolvedAt: null,
      },
      orderBy: { activatedAt: 'desc' },
    });
  }

  /**
   * Get protocol by type
   */
  async getProtocolByType(crisisType: string) {
    return await prisma.crisisProtocol.findFirst({
      where: {
        crisisType,
        status: 'active',
      },
    });
  }
}

export const crisisManagementService = new CrisisManagementService();

