// GRU International Adoption Service
// Implements 3-phase adoption model: Alignment → Integration → Expansion

import prisma from '@/shared/database/prisma';
import { v4 as uuidv4 } from 'uuid';
import { logger } from '@/infrastructure/monitoring/logger';
import { gruRegulatoryClassificationService } from './gru-regulatory-classification.service';
import { gruSupranationalGovernanceService } from './gru-supranational-governance.service';
import { gruLegalFrameworkService } from './gru-legal-framework.service';


export type AdoptionPhase = 'alignment' | 'integration' | 'expansion';
export type PhaseStatus = 'pending' | 'in_progress' | 'completed';

export interface InitiateAdoptionRequest {
  entityId: string;
  entityType: 'sovereign_bank' | 'supranational_entity' | 'regional_union';
  regulatoryClass?: 'SR-1' | 'SR-2' | 'SR-3' | 'M0' | 'M1';
}

export interface AdoptionStatus {
  adoptionId: string;
  entityId: string;
  currentPhase: AdoptionPhase;
  alignmentStatus: PhaseStatus;
  integrationStatus: PhaseStatus;
  expansionStatus: PhaseStatus;
  overallStatus: string;
}

export class GruAdoptionService {
  /**
   * Initiate adoption process
   */
  async initiateAdoption(
    request: InitiateAdoptionRequest
  ): Promise<{ adoptionId: string; status: string }> {
    logger.info('GRU Adoption: Initiating adoption process', { request });

    // Create adoption record
    const adoption = await prisma.gru_adoptions.create({
      data: {
        id: uuidv4(),
        adoptionId: `GRU-ADOPT-${uuidv4()}`,
        entityId: request.entityId,
        entityType: request.entityType,
        currentPhase: 'alignment',
        alignmentStatus: 'pending',
        integrationStatus: 'pending',
        expansionStatus: 'pending',
        status: 'active',
        createdAt: new Date(),
        updatedAt: new Date(),
      },
    });

    // Automatically start alignment phase
    await this.startAlignmentPhase(adoption.adoptionId, request);

    logger.info('GRU Adoption: Adoption process initiated', {
      adoptionId: adoption.adoptionId,
    });

    return {
      adoptionId: adoption.adoptionId,
      status: 'active',
        createdAt: new Date(),
        updatedAt: new Date(),
    };
  }

  /**
   * Get adoption status
   */
  async getAdoptionStatus(adoptionId: string): Promise<AdoptionStatus> {
    const adoption = await prisma.gru_adoptions.findUnique({
      where: { adoptionId },
    });

    if (!adoption) {
      throw new Error(`Adoption not found: ${adoptionId}`);
    }

    return {
      adoptionId: adoption.adoptionId,
      entityId: adoption.entityId,
      currentPhase: adoption.currentPhase as AdoptionPhase,
      alignmentStatus: adoption.alignmentStatus as PhaseStatus,
      integrationStatus: adoption.integrationStatus as PhaseStatus,
      expansionStatus: adoption.expansionStatus as PhaseStatus,
      overallStatus: adoption.status,
    };
  }

  /**
   * Advance to next phase
   */
  async advanceToPhase(
    adoptionId: string,
    phase: AdoptionPhase
  ): Promise<void> {
    logger.info('GRU Adoption: Advancing to phase', { adoptionId, phase });

    const adoption = await prisma.gru_adoptions.findUnique({
      where: { adoptionId },
    });

    if (!adoption) {
      throw new Error(`Adoption not found: ${adoptionId}`);
    }

    // Validate phase progression
    this.validatePhaseProgression(adoption.currentPhase, phase);

    // Update phase status
    const updateData: any = {
      currentPhase: phase,
    };

    switch (phase) {
      case 'alignment':
        updateData.alignmentStatus = 'in_progress';
        break;
      case 'integration':
        updateData.integrationStatus = 'in_progress';
        // Complete alignment if not already completed
        if (adoption.alignmentStatus !== 'completed') {
          updateData.alignmentStatus = 'completed';
          updateData.regulatorySyncDate = new Date();
        }
        break;
      case 'expansion':
        updateData.expansionStatus = 'in_progress';
        // Complete integration if not already completed
        if (adoption.integrationStatus !== 'completed') {
          updateData.integrationStatus = 'completed';
          updateData.reserveConversionDate = new Date();
        }
        break;
    }

    await prisma.gru_adoptions.update({
      where: { adoptionId },
      data: updateData,
    });

    // Execute phase-specific logic
    switch (phase) {
      case 'alignment':
        await this.executeAlignmentPhase(adoptionId);
        break;
      case 'integration':
        await this.executeIntegrationPhase(adoptionId);
        break;
      case 'expansion':
        await this.executeExpansionPhase(adoptionId);
        break;
    }

    logger.info('GRU Adoption: Phase advanced', { adoptionId, phase });
  }

  /**
   * Start alignment phase
   */
  private async startAlignmentPhase(
    adoptionId: string,
    request: InitiateAdoptionRequest
  ): Promise<void> {
    logger.info('GRU Adoption: Starting alignment phase', { adoptionId });

    // Phase 1: Alignment Phase - Regulatory synchronization
    // This involves:
    // 1. Regulatory classification
    // 2. Legal framework compliance
    // 3. Regulatory synchronization

    // Classify entity if regulatory class provided
    if (request.regulatoryClass) {
      await gruRegulatoryClassificationService.classifyEntity({
        entityId: request.entityId,
        entityType: this.mapEntityType(request.entityType),
        regulatoryClass: request.regulatoryClass,
        reserveAdequacy: true, // Should be verified
        legalRecognition: true, // Should be verified
        ilieVerified: true, // Should be verified via ILIE
      });
    }

    // Verify legal framework compliance
    await gruLegalFrameworkService.initializeFrameworks();

    // Update adoption status
    await prisma.gru_adoptions.update({
      where: { adoptionId },
      data: {
        alignmentStatus: 'in_progress',
        regulatorySyncDate: new Date(),
      },
    });

    logger.info('GRU Adoption: Alignment phase started', { adoptionId });
  }

  /**
   * Execute alignment phase
   */
  private async executeAlignmentPhase(adoptionId: string): Promise<void> {
    // Complete alignment phase
    await prisma.gru_adoptions.update({
      where: { adoptionId },
      data: {
        alignmentStatus: 'completed',
        regulatorySyncDate: new Date(),
      },
    });

    logger.info('GRU Adoption: Alignment phase completed', { adoptionId });
  }

  /**
   * Execute integration phase
   */
  private async executeIntegrationPhase(adoptionId: string): Promise<void> {
    logger.info('GRU Adoption: Executing integration phase', { adoptionId });

    // Phase 2: Integration Phase - GRU issuance & reserve conversion
    // This involves:
    // 1. First GRU issuance through governance pathway
    // 2. Reserve conversion
    // 3. Integration with existing systems

    const adoption = await prisma.gru_adoptions.findUnique({
      where: { adoptionId },
    });

    if (!adoption) {
      throw new Error(`Adoption not found: ${adoptionId}`);
    }

    // The actual issuance would be done through the governance service
    // This is just marking the phase as in progress

    await prisma.gru_adoptions.update({
      where: { adoptionId },
      data: {
        integrationStatus: 'in_progress',
        reserveConversionDate: new Date(),
      },
    });

    logger.info('GRU Adoption: Integration phase in progress', { adoptionId });
  }

  /**
   * Execute expansion phase
   */
  private async executeExpansionPhase(adoptionId: string): Promise<void> {
    logger.info('GRU Adoption: Executing expansion phase', { adoptionId });

    // Phase 3: Expansion Phase - Regional pool participation
    // This involves:
    // 1. Joining regional reserve pools
    // 2. Participating in regional stabilization
    // 3. Cross-sovereign GRU operations

    await prisma.gru_adoptions.update({
      where: { adoptionId },
      data: {
        expansionStatus: 'in_progress',
        regionalPoolJoinDate: new Date(),
      },
    });

    logger.info('GRU Adoption: Expansion phase in progress', { adoptionId });
  }

  /**
   * Complete adoption
   */
  async completeAdoption(adoptionId: string): Promise<void> {
    const adoption = await prisma.gru_adoptions.findUnique({
      where: { adoptionId },
    });

    if (!adoption) {
      throw new Error(`Adoption not found: ${adoptionId}`);
    }

    // Verify all phases are completed
    if (
      adoption.alignmentStatus !== 'completed' ||
      adoption.integrationStatus !== 'completed' ||
      adoption.expansionStatus !== 'completed'
    ) {
      throw new Error('Cannot complete adoption: not all phases are completed');
    }

    await prisma.gru_adoptions.update({
      where: { adoptionId },
      data: {
        status: 'completed',
        completedAt: new Date(),
      },
    });

    logger.info('GRU Adoption: Adoption completed', { adoptionId });
  }

  /**
   * Validate phase progression
   */
  private validatePhaseProgression(
    currentPhase: string,
    targetPhase: AdoptionPhase
  ): void {
    const phaseOrder: AdoptionPhase[] = ['alignment', 'integration', 'expansion'];
    const currentIndex = phaseOrder.indexOf(currentPhase as AdoptionPhase);
    const targetIndex = phaseOrder.indexOf(targetPhase);

    if (targetIndex < currentIndex) {
      throw new Error(
        `Cannot move backwards from ${currentPhase} to ${targetPhase}`
      );
    }

    if (targetIndex > currentIndex + 1) {
      throw new Error(
        `Cannot skip phases: current is ${currentPhase}, target is ${targetPhase}`
      );
    }
  }

  /**
   * Map entity type
   */
  private mapEntityType(
    entityType: 'sovereign_bank' | 'supranational_entity' | 'regional_union'
  ): 'sovereign_bank' | 'supranational_council' | 'regional_union' | 'institution' | 'commercial' {
    switch (entityType) {
      case 'sovereign_bank':
        return 'sovereign_bank';
      case 'supranational_entity':
        return 'supranational_council';
      case 'regional_union':
        return 'regional_union';
      default:
        return 'institution';
    }
  }
}

export const gruAdoptionService = new GruAdoptionService();

