// GDSL Contract Service
// Smart contract binding and execution

import prisma from '@/shared/database/prisma';
import { v4 as uuidv4 } from 'uuid';
import { contractFabricService } from '@/core/contracts/contract-fabric.service';


export interface ContractBindingRequest {
  contractId: string;
  smartContractTemplate?: string;
}

export interface ContractExecutionRequest {
  contractId: string;
  executionConditions: Record<string, unknown>;
}

export class GdslContractService {
  /**
   * Bind smart contract to derivative
   */
  async bindSmartContract(
    request: ContractBindingRequest
  ): Promise<{ smartContractId: string }> {
    const contract = await prisma.derivative_contracts.findUnique({
      where: { contractId: request.contractId },
    });

    if (!contract) {
      throw new Error(`Derivative contract not found: ${request.contractId}`);
    }

    // Create smart contract
    const smartContract = await contractFabricService.createContract(
      contract.party1BankId,
      'DERIVATIVE_CLEARING' as any,
      {
        contractId: request.contractId,
        derivativeType: contract.derivativeType,
        notionalAmount: contract.notionalAmount.toString(),
        ...(typeof contract.contractTerms === 'object' && contract.contractTerms !== null ? contract.contractTerms : {}),
      },
      [contract.party1BankId, contract.party2BankId]
    );

    // Update derivative contract
    await prisma.derivative_contracts.update({
      where: { contractId: request.contractId },
      data: {
        smartContractId: smartContract.contractId,
      },
    });

    return {
      smartContractId: smartContract.contractId,
    };
  }

  /**
   * Execute derivative contract
   */
  async executeContract(
    request: ContractExecutionRequest
  ): Promise<{ executed: boolean }> {
    const contract = await prisma.derivative_contracts.findUnique({
      where: { contractId: request.contractId },
    });

    if (!contract) {
      throw new Error(`Derivative contract not found: ${request.contractId}`);
    }

    if (!contract.smartContractId) {
      throw new Error(`No smart contract bound to derivative: ${request.contractId}`);
    }

    // Execute smart contract
    await contractFabricService.executeContract(
      contract.smartContractId,
      {
        executionConditions: request.executionConditions,
        executedAt: new Date().toISOString(),
      }
    );

    // Update derivative contract status
    await prisma.derivative_contracts.update({
      where: { contractId: request.contractId },
      data: {
        status: 'settled',
      },
    });

    return { executed: true };
  }

  /**
   * Get contract execution status
   */
  async getContractStatus(contractId: string): Promise<{
    status: string;
    smartContractId?: string;
    executionResult?: Record<string, unknown>;
  }> {
    const contract = await prisma.derivative_contracts.findUnique({
      where: { contractId },
      select: {
        status: true,
        smartContractId: true,
      },
    });

    if (!contract) {
      throw new Error(`Derivative contract not found: ${contractId}`);
    }

    let executionResult: Record<string, unknown> | undefined;

    if (contract.smartContractId) {
      const smartContract = await prisma.smart_contracts.findUnique({
        where: { contractId: contract.smartContractId },
        select: { executionResult: true },
      });

      executionResult = smartContract?.executionResult as Record<string, unknown> | undefined;
    }

    return {
      status: contract.status,
      smartContractId: contract.smartContractId || undefined,
      executionResult,
    };
  }
}

export const gdslContractService = new GdslContractService();

