// GRU Supranational Governance Service
// Implements issuance pathway: Application → Eligibility Review → Index Validation → Allocation → Registration → GAS Settlement → Ω-Layer Finality

import prisma from '@/shared/database/prisma';
import { Decimal } from '@prisma/client/runtime/library';
import { v4 as uuidv4 } from 'uuid';
import { logger } from '@/infrastructure/monitoring/logger';
import { gruRegulatoryClassificationService } from './gru-regulatory-classification.service';
import { gruIndexService, GruIndexCode } from './gru-index.service';
import { gruLegalRegistrationService } from './gru-legal-registration.service';
import { gruIssuanceService } from './gru-issuance.service';


export type IssuancePathwayStep =
  | 'application'
  | 'eligibility_review'
  | 'index_validation'
  | 'allocation'
  | 'registration'
  | 'gas_settlement'
  | 'omega_finality';

export interface IssuanceApplicationRequest {
  entityId: string;
  entityType: 'supranational_entity' | 'sovereign_bank';
  requestedAmount: string;
  requestedUnitType: 'M00' | 'M0' | 'M1';
  requestedIndexLink: GruIndexCode;
  regulatoryClass?: 'SR-1' | 'SR-2' | 'SR-3' | 'M0' | 'M1';
}

export interface IssuancePathwayStatus {
  applicationId: string;
  currentStep: IssuancePathwayStep;
  status: string;
  eligibilityReview?: any;
  indexValidation?: any;
  allocation?: any;
  issuance?: any;
  settlementPipeline?: any;
}

export class GruSupranationalGovernanceService {
  /**
   * Submit issuance application
   */
  async submitApplication(
    request: IssuanceApplicationRequest
  ): Promise<{ applicationId: string; status: string }> {
    logger.info('GRU Supranational Governance: Submitting application', { request });

    // Create application
    const application = await prisma.gruIssuanceApplication.create({
      data: {
        applicationId: `GRU-APP-${uuidv4()}`,
        entityId: request.entityId,
        entityType: request.entityType,
        requestedAmount: new Decimal(request.requestedAmount),
        requestedUnitType: request.requestedUnitType,
        requestedIndexLink: request.requestedIndexLink,
        regulatoryClass: request.regulatoryClass,
        status: 'submitted',
        currentStep: 'application',
      },
    });

    // Automatically proceed to eligibility review
    await this.proceedToEligibilityReview(application.applicationId);

    logger.info('GRU Supranational Governance: Application submitted', {
      applicationId: application.applicationId,
    });

    return {
      applicationId: application.applicationId,
      status: 'submitted',
    };
  }

  /**
   * Get application status
   */
  async getApplicationStatus(applicationId: string): Promise<IssuancePathwayStatus> {
    const application = await prisma.gruIssuanceApplication.findUnique({
      where: { applicationId },
      include: {
        eligibilityReview: true,
        indexValidation: true,
        allocation: {
          include: {
            issuance: true,
          },
        },
        issuance: true,
      },
    });

    if (!application) {
      throw new Error(`Application not found: ${applicationId}`);
    }

    // Get settlement pipeline if issuance exists
    let settlementPipeline = null;
    if (application.issuance) {
      settlementPipeline = await prisma.gruSettlementPipeline.findFirst({
        where: { issuanceId: application.issuance.issuanceId },
        include: {
          gasSettlement: true,
          omegaFinality: true,
        },
      });
    }

    return {
      applicationId: application.applicationId,
      currentStep: application.currentStep as IssuancePathwayStep,
      status: application.status,
      eligibilityReview: application.eligibilityReview,
      indexValidation: application.indexValidation,
      allocation: application.allocation,
      issuance: application.issuance,
      settlementPipeline,
    };
  }

  /**
   * Proceed to eligibility review
   */
  private async proceedToEligibilityReview(applicationId: string): Promise<void> {
    const application = await prisma.gruIssuanceApplication.findUnique({
      where: { applicationId },
    });

    if (!application) {
      throw new Error(`Application not found: ${applicationId}`);
    }

    // Check eligibility via regulatory classification service
    const eligibility = await gruRegulatoryClassificationService.checkEligibility(
      application.entityId
    );

    // Create eligibility review
    const review = await prisma.gruEligibilityReview.create({
      data: {
        reviewId: `GRU-REV-${uuidv4()}`,
        applicationId,
        reviewType: 'initial',
        sovereignStatus: application.entityType === 'sovereign_bank',
        reserveAdequacy: eligibility.eligible, // Simplified - should check actual reserve adequacy
        legalRecognition: eligibility.eligible, // Simplified - should check actual legal recognition
        ilieVerification: eligibility.eligible, // Simplified - should check actual ILIE verification
        reviewResult: eligibility.eligible ? 'approved' : 'pending',
        reviewedAt: new Date(),
      },
    });

    // Update application status
    if (eligibility.eligible) {
      await prisma.gruIssuanceApplication.update({
        where: { applicationId },
        data: {
          status: 'eligibility_review',
          currentStep: 'index_validation',
        },
      });

      // Automatically proceed to index validation
      await this.proceedToIndexValidation(applicationId);
    } else {
      await prisma.gruIssuanceApplication.update({
        where: { applicationId },
        data: {
          status: 'eligibility_review',
          currentStep: 'eligibility_review',
        },
      });
    }

    logger.info('GRU Supranational Governance: Eligibility review completed', {
      applicationId,
      reviewResult: review.reviewResult,
    });
  }

  /**
   * Proceed to index validation
   */
  private async proceedToIndexValidation(applicationId: string): Promise<void> {
    const application = await prisma.gruIssuanceApplication.findUnique({
      where: { applicationId },
    });

    if (!application) {
      throw new Error(`Application not found: ${applicationId}`);
    }

    // Validate index exists and is active
    const index = await gruIndexService.getIndex(application.requestedIndexLink);
    if (!index || index.status !== 'active') {
      throw new Error(`Index ${application.requestedIndexLink} is not available`);
    }

    // Create index validation
    const validation = await prisma.gruIndexValidation.create({
      data: {
        validationId: `GRU-VAL-${uuidv4()}`,
        applicationId,
        indexCode: application.requestedIndexLink,
        indexValue: index.currentValue,
        validationResult: 'valid',
        validatedAt: new Date(),
      },
    });

    // Update application status
    await prisma.gruIssuanceApplication.update({
      where: { applicationId },
      data: {
        status: 'index_validation',
        currentStep: 'allocation',
      },
    });

    // Automatically proceed to allocation
    await this.proceedToAllocation(applicationId);

    logger.info('GRU Supranational Governance: Index validation completed', {
      applicationId,
      validationResult: validation.validationResult,
    });
  }

  /**
   * Proceed to allocation
   */
  private async proceedToAllocation(applicationId: string): Promise<void> {
    const application = await prisma.gruIssuanceApplication.findUnique({
      where: { applicationId },
    });

    if (!application) {
      throw new Error(`Application not found: ${applicationId}`);
    }

    // Create issuance via issuance service
    const issuanceResult = await gruIssuanceService.issueGru({
      sovereignBankId: application.entityId,
      issuanceClass: this.mapRegulatoryClassToIssuanceClass(application.regulatoryClass),
      amount: application.requestedAmount.toString(),
      unitType: application.requestedUnitType,
      metalIndexLink: application.requestedIndexLink,
      registrarOfficeId: 'DBIS-REGISTRAR-001', // Default registrar
    });

    // Create allocation record
    const allocation = await prisma.gruAllocationRecord.create({
      data: {
        allocationId: `GRU-ALLOC-${uuidv4()}`,
        applicationId,
        issuanceId: issuanceResult.issuanceId,
        allocatedAmount: issuanceResult.amount,
        allocatedUnitType: issuanceResult.unitType,
        status: 'allocated',
      },
    });

    // Update application status
    await prisma.gruIssuanceApplication.update({
      where: { applicationId },
      data: {
        status: 'allocation',
        currentStep: 'registration',
      },
    });

    // Automatically proceed to registration (handled by issuance service)
    // Then proceed to GAS settlement
    await this.proceedToGasSettlement(issuanceResult.issuanceId);

    logger.info('GRU Supranational Governance: Allocation completed', {
      applicationId,
      allocationId: allocation.allocationId,
      issuanceId: issuanceResult.issuanceId,
    });
  }

  /**
   * Proceed to GAS settlement
   */
  private async proceedToGasSettlement(issuanceId: string): Promise<void> {
    // This will be handled by the settlement pipeline service
    // For now, we'll create a placeholder
    logger.info('GRU Supranational Governance: Proceeding to GAS settlement', {
      issuanceId,
    });
  }

  /**
   * Approve application (manual approval step)
   */
  async approveApplication(applicationId: string): Promise<void> {
    const application = await prisma.gruIssuanceApplication.findUnique({
      where: { applicationId },
    });

    if (!application) {
      throw new Error(`Application not found: ${applicationId}`);
    }

    // Verify all steps are completed
    if (application.currentStep !== 'omega_finality') {
      throw new Error(
        `Application cannot be approved: current step is ${application.currentStep}, expected omega_finality`
      );
    }

    await prisma.gruIssuanceApplication.update({
      where: { applicationId },
      data: {
        status: 'approved',
        completedAt: new Date(),
      },
    });

    logger.info('GRU Supranational Governance: Application approved', {
      applicationId,
    });
  }

  /**
   * Get issuance pathway status
   */
  async getIssuancePathway(issuanceId: string): Promise<IssuancePathwayStatus> {
    const issuance = await prisma.gruIssuance.findUnique({
      where: { issuanceId },
    });

    if (!issuance) {
      throw new Error(`Issuance not found: ${issuanceId}`);
    }

    const application = await prisma.gruIssuanceApplication.findFirst({
      where: {
        issuance: {
          issuanceId,
        },
      },
      include: {
        eligibilityReview: true,
        indexValidation: true,
        allocation: true,
      },
    });

    const settlementPipeline = await prisma.gruSettlementPipeline.findFirst({
      where: { issuanceId },
      include: {
        gasSettlement: true,
        omegaFinality: true,
      },
    });

    return {
      applicationId: application?.applicationId || 'N/A',
      currentStep: settlementPipeline
        ? (settlementPipeline.pipelineStage as IssuancePathwayStep)
        : 'application',
      status: issuance.status,
      eligibilityReview: application?.eligibilityReview,
      indexValidation: application?.indexValidation,
      allocation: application?.allocation,
      issuance,
      settlementPipeline,
    };
  }

  /**
   * Map regulatory class to issuance class
   */
  private mapRegulatoryClassToIssuanceClass(
    regulatoryClass: string | null | undefined
  ): 'Class_I' | 'Class_II' | 'Class_III' | 'Class_IV' {
    switch (regulatoryClass) {
      case 'SR-1':
        return 'Class_I';
      case 'SR-2':
        return 'Class_II';
      case 'SR-3':
        return 'Class_II';
      case 'M0':
        return 'Class_III';
      case 'M1':
        return 'Class_IV';
      default:
        return 'Class_II';
    }
  }
}

export const gruSupranationalGovernanceService = new GruSupranationalGovernanceService();

