// Cross-Chain Settlement Service
// Atomic cross-chain swaps
// Multi-leg hybrid swaps
// Chain type support: DBIS sovereign, SCB CBDC, commodity, security chains

import prisma from '@/shared/database/prisma';
import { Decimal } from '@prisma/client/runtime/library';
import { v4 as uuidv4 } from 'uuid';
import { crossChainVerificationService } from './cross-chain-verification.service';
import { crossChainContractService } from './cross-chain-contract.service';
import { createHash } from 'crypto';


export interface CrossChainSettlementRequest {
  sourceChainType: string;
  sourceChainId: string;
  targetChainType: string;
  targetChainId: string;
  sourceBankId: string;
  destinationBankId: string;
  amount: string;
  assetType: string;
}

export class CrossChainSettlementService {
  /**
   * Execute cross-chain settlement
   */
  async executeCrossChainSettlement(
    request: CrossChainSettlementRequest
  ): Promise<string> {
    const settlementId = `CCS-${uuidv4()}`;

    // Create settlement record
    const settlement = await prisma.crossChainSettlement.create({
      data: {
        settlementId,
        sourceChainType: request.sourceChainType,
        sourceChainId: request.sourceChainId,
        targetChainType: request.targetChainType,
        targetChainId: request.targetChainId,
        sourceBankId: request.sourceBankId,
        destinationBankId: request.destinationBankId,
        amount: new Decimal(request.amount),
        assetType: request.assetType,
        status: 'pending',
      },
    });

    // Create cross-chain commitments
    await this.createCommitments(settlementId, request);

    // Execute atomic swap using contract
    const success = await crossChainContractService.executeAtomicSwap(
      settlementId,
      request.sourceBankId,
      request.destinationBankId
    );

    if (success) {
      await prisma.crossChainSettlement.update({
        where: { settlementId },
        data: {
          status: 'settled',
          settledAt: new Date(),
        },
      });
    } else {
      await prisma.crossChainSettlement.update({
        where: { settlementId },
        data: {
          status: 'failed',
        },
      });

      throw new Error('Cross-chain settlement failed');
    }

    return settlementId;
  }

  /**
   * Create cross-chain commitments
   */
  private async createCommitments(
    settlementId: string,
    request: CrossChainSettlementRequest
  ): Promise<void> {
    // Create SCB1 commitment
    await prisma.crossChainCommitment.create({
      data: {
        commitmentId: `CCC-${uuidv4()}`,
        settlementId,
        chainId: request.sourceBankId,
        commitmentHash: this.generateCommitmentHash(settlementId, request.sourceBankId),
        commitmentType: 'scb1_commit',
        status: 'pending',
      },
    });

    // Create SCB2 commitment
    await prisma.crossChainCommitment.create({
      data: {
        commitmentId: `CCC-${uuidv4()}`,
        settlementId,
        chainId: request.destinationBankId,
        commitmentHash: this.generateCommitmentHash(settlementId, request.destinationBankId),
        commitmentType: 'scb2_commit',
        status: 'pending',
      },
    });

    // Create DBIS commitment
    await prisma.crossChainCommitment.create({
      data: {
        commitmentId: `CCC-${uuidv4()}`,
        settlementId,
        chainId: 'DBIS',
        commitmentHash: this.generateCommitmentHash(settlementId, 'DBIS'),
        commitmentType: 'dbis_commit',
        status: 'pending',
      },
    });
  }

  /**
   * Generate commitment hash
   */
  private generateCommitmentHash(
    settlementId: string,
    chainId: string
  ): string {
    const data = {
      settlementId,
      chainId,
      timestamp: new Date().toISOString(),
    };

    return createHash('sha3-256')
      .update(JSON.stringify(data))
      .digest('hex');
  }

  /**
   * Execute multi-leg hybrid swap
   */
  async executeMultiLegHybridSwap(
    legs: Array<{
      chainType: string;
      chainId: string;
      sourceBankId: string;
      destinationBankId: string;
      amount: string;
      assetType: string;
    }>
  ): Promise<string[]> {
    const settlementIds: string[] = [];

    try {
      // Execute all legs
      for (let i = 0; i < legs.length; i++) {
        const leg = legs[i];
        const nextLeg = legs[i + 1];

        const request: CrossChainSettlementRequest = {
          sourceChainType: leg.chainType,
          sourceChainId: leg.chainId,
          targetChainType: nextLeg?.chainType || leg.chainType,
          targetChainId: nextLeg?.chainId || leg.chainId,
          sourceBankId: leg.sourceBankId,
          destinationBankId: leg.destinationBankId,
          amount: leg.amount,
          assetType: leg.assetType,
        };

        const settlementId = await this.executeCrossChainSettlement(request);
        settlementIds.push(settlementId);
      }

      return settlementIds;
    } catch (error) {
      // Rollback on error
      for (const settlementId of settlementIds) {
        try {
          await prisma.crossChainSettlement.update({
            where: { settlementId },
            data: {
              status: 'failed',
            },
          });
        } catch (rollbackError) {
          // Ignore rollback errors
        }
      }

      throw error;
    }
  }

  /**
   * Get supported chain types
   */
  getSupportedChainTypes(): string[] {
    return [
      'dbis_sovereign',
      'scb_cbdc',
      'commodity_tokenization',
      'security_token',
    ];
  }

  /**
   * Get settlement by ID
   */
  async getSettlement(settlementId: string) {
    return await prisma.crossChainSettlement.findUnique({
      where: { settlementId },
      include: {
        commitments: true,
        chainHeaders: true,
      },
    });
  }

  /**
   * Get settlements for chain
   */
  async getSettlementsForChain(
    chainType: string,
    chainId: string,
    limit: number = 100
  ) {
    return await prisma.crossChainSettlement.findMany({
      where: {
        OR: [
          {
            sourceChainType: chainType,
            sourceChainId: chainId,
          },
          {
            targetChainType: chainType,
            targetChainId: chainId,
          },
        ],
      },
      orderBy: { createdAt: 'desc' },
      take: limit,
    });
  }
}

export const crossChainSettlementService = new CrossChainSettlementService();

