// Temenos Core Banking Adapter
// Maps Temenos T24/Temenos Transact internal schemas to DBIS Nostro/Vostro API

import { BasePluginAdapter } from './generic-adapter';
import {
  ParticipantCreateRequest,
  AccountCreateRequest,
  TransferCreateRequest,
  NostroVostroTransfer,
  NostroVostroAccount,
  AccountType,
} from '@/core/nostro-vostro/nostro-vostro.types';

/**
 * Temenos internal data structures (simplified)
 */
interface TemenosCustomer {
  customerId: string;
  shortName: string;
  name: string;
  bic?: string;
  lei?: string;
  country: string;
  sector: string; // e.g., "1001" for banks
}

interface TemenosAccount {
  accountId: string;
  customerId: string;
  accountNumber: string;
  currency: string;
  accountType: string; // NOSTRO, VOSTRO
  workingBalance: number;
  availableBalance: number;
  reservedAmount: number;
  status: string;
}

interface TemenosTransaction {
  transactionId: string;
  debitAccount: string;
  creditAccount: string;
  amount: number;
  currency: string;
  valueDate: string;
  narrative: string;
  transactionCode: string;
}

export class TemenosAdapter extends BasePluginAdapter {
  private apiEndpoint?: string;
  private apiKey?: string;

  constructor(config: Record<string, unknown> = {}) {
    super('Temenos', '1.0.0', config);
    this.apiEndpoint = config.apiEndpoint as string;
    this.apiKey = config.apiKey as string;
  }

  async isAvailable(): Promise<boolean> {
    // Check Temenos API connectivity
    if (!this.apiEndpoint) {
      return false;
    }

    try {
      // In production, make actual API call
      // const response = await fetch(`${this.apiEndpoint}/health`, {
      //   headers: { 'Authorization': `Bearer ${this.apiKey}` }
      // });
      // return response.ok;
      return true; // Mock for now
    } catch {
      return false;
    }
  }

  mapParticipant(internalData: unknown): ParticipantCreateRequest {
    const customer = internalData as TemenosCustomer;

    // Map Temenos sector to regulatory tier
    const regulatoryTierMap: Record<string, string> = {
      '1001': 'SCB', // Central Bank
      '1002': 'Tier1', // Commercial Bank
      '1003': 'Tier2', // Other Financial Institution
      '1004': 'PSP', // Payment Service Provider
    };

    return {
      participantId: customer.customerId,
      name: customer.name || customer.shortName,
      bic: customer.bic,
      lei: customer.lei,
      country: customer.country,
      regulatoryTier: regulatoryTierMap[customer.sector] || 'Tier2',
      metadata: {
        temenosCustomerId: customer.customerId,
        temenosSector: customer.sector,
      },
    };
  }

  mapAccount(internalData: unknown): AccountCreateRequest {
    const account = internalData as TemenosAccount;

    return {
      ownerParticipantId: account.customerId,
      counterpartyParticipantId: account.customerId, // Would need to be determined from account relationship
      ibanOrLocalAccount: account.accountNumber,
      currency: account.currency,
      accountType: account.accountType === 'NOSTRO' ? AccountType.NOSTRO : AccountType.VOSTRO,
      metadata: {
        temenosAccountId: account.accountId,
        temenosAccountNumber: account.accountNumber,
      },
    };
  }

  mapTransfer(internalData: unknown): TransferCreateRequest {
    const transaction = internalData as TemenosTransaction;

    return {
      fromAccountId: transaction.debitAccount,
      toAccountId: transaction.creditAccount,
      amount: transaction.amount.toString(),
      currency: transaction.currency,
      valueDate: transaction.valueDate,
      reference: transaction.narrative,
      metadata: {
        temenosTransactionId: transaction.transactionId,
        temenosTransactionCode: transaction.transactionCode,
      },
    };
  }

  mapTransferToInternal(transfer: NostroVostroTransfer): unknown {
    return {
      transactionId: transfer.transferId,
      debitAccount: transfer.fromAccountId,
      creditAccount: transfer.toAccountId,
      amount: parseFloat(transfer.amount),
      currency: transfer.currency,
      valueDate: transfer.valueDate.toISOString().split('T')[0],
      narrative: transfer.reference || `DBIS Transfer ${transfer.transferId}`,
      transactionCode: 'FT', // Funds Transfer
      metadata: {
        dbisTransferId: transfer.transferId,
        settlementAsset: transfer.settlementAsset,
      },
    };
  }

  mapAccountToInternal(account: NostroVostroAccount): unknown {
    return {
      accountId: account.accountId,
      accountNumber: account.ibanOrLocalAccount,
      currency: account.currency,
      accountType: account.accountType,
      workingBalance: parseFloat(account.currentBalance),
      availableBalance: parseFloat(account.availableLiquidity),
      reservedAmount: parseFloat(account.holdAmount),
      status: account.status,
    };
  }

  async postTransfer(transfer: NostroVostroTransfer): Promise<{ success: boolean; internalId?: string; error?: string }> {
    try {
      const temenosTransaction = this.mapTransferToInternal(transfer);

      // In production, post to Temenos API
      // const response = await fetch(`${this.apiEndpoint}/transactions`, {
      //   method: 'POST',
      //   headers: {
      //     'Authorization': `Bearer ${this.apiKey}`,
      //     'Content-Type': 'application/json'
      //   },
      //   body: JSON.stringify(temenosTransaction)
      // });

      // Mock response
      const internalId = this.generateInternalReference('TXN');
      return { success: true, internalId };
    } catch (error) {
      return this.handleError(error, 'postTransfer');
    }
  }

  async getAccountBalance(accountId: string): Promise<{ balance: string; available: string; hold: string }> {
    try {
      // In production, query Temenos API
      // const response = await fetch(`${this.apiEndpoint}/accounts/${accountId}/balance`, {
      //   headers: { 'Authorization': `Bearer ${this.apiKey}` }
      // });

      // Mock response
      return {
        balance: '0',
        available: '0',
        hold: '0',
      };
    } catch (error) {
      throw new Error(`Failed to get balance: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }

  async reconcile(accountId: string, asOfDate: Date): Promise<{ matched: number; breaks: unknown[] }> {
    try {
      // In production, query Temenos reconciliation API
      // Mock response
      return {
        matched: 0,
        breaks: [],
      };
    } catch (error) {
      throw new Error(`Reconciliation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }
}

