// Flexcube Core Banking Adapter
// Maps Oracle Flexcube 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';

/**
 * Flexcube internal data structures (simplified)
 */
interface FlexcubeCustomer {
  customerNo: string;
  customerName: string;
  bic?: string;
  lei?: string;
  countryCode: string;
  customerCategory: string; // BANK, FI, etc.
}

interface FlexcubeAccount {
  accountNo: string;
  customerNo: string;
  currency: string;
  accountClass: string; // NOSTRO, VOSTRO
  balance: number;
  availableBalance: number;
  blockedAmount: number;
  accountStatus: string;
}

interface FlexcubeTransaction {
  transactionRef: string;
  debitAccount: string;
  creditAccount: string;
  amount: number;
  currency: string;
  valueDate: string;
  transactionNarrative: string;
  transactionType: string;
}

export class FlexcubeAdapter extends BasePluginAdapter {
  private dbConnection?: string;
  private apiEndpoint?: string;

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

  async isAvailable(): Promise<boolean> {
    // Check Flexcube connectivity (DB or API)
    if (!this.dbConnection && !this.apiEndpoint) {
      return false;
    }

    try {
      // In production, check DB connection or API health
      return true; // Mock for now
    } catch {
      return false;
    }
  }

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

    // Map Flexcube category to regulatory tier
    const regulatoryTierMap: Record<string, string> = {
      BANK: 'Tier1',
      CENTRAL_BANK: 'SCB',
      FINANCIAL_INSTITUTION: 'Tier2',
      PAYMENT_PROVIDER: 'PSP',
    };

    return {
      participantId: customer.customerNo,
      name: customer.customerName,
      bic: customer.bic,
      lei: customer.lei,
      country: customer.countryCode,
      regulatoryTier: regulatoryTierMap[customer.customerCategory] || 'Tier2',
      metadata: {
        flexcubeCustomerNo: customer.customerNo,
        flexcubeCategory: customer.customerCategory,
      },
    };
  }

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

    return {
      ownerParticipantId: account.customerNo,
      counterpartyParticipantId: account.customerNo, // Would need relationship lookup
      ibanOrLocalAccount: account.accountNo,
      currency: account.currency,
      accountType: account.accountClass === 'NOSTRO' ? AccountType.NOSTRO : AccountType.VOSTRO,
      metadata: {
        flexcubeAccountNo: account.accountNo,
      },
    };
  }

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

    return {
      fromAccountId: transaction.debitAccount,
      toAccountId: transaction.creditAccount,
      amount: transaction.amount.toString(),
      currency: transaction.currency,
      valueDate: transaction.valueDate,
      reference: transaction.transactionNarrative,
      metadata: {
        flexcubeTransactionRef: transaction.transactionRef,
        flexcubeTransactionType: transaction.transactionType,
      },
    };
  }

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

  mapAccountToInternal(account: NostroVostroAccount): unknown {
    return {
      accountNo: account.accountId,
      currency: account.currency,
      accountClass: account.accountType,
      balance: parseFloat(account.currentBalance),
      availableBalance: parseFloat(account.availableLiquidity),
      blockedAmount: parseFloat(account.holdAmount),
      accountStatus: account.status,
    };
  }

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

      // In production, post to Flexcube (DB or API)
      // Mock response
      const internalId = this.generateInternalReference('FC');
      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 Flexcube DB or API
      // 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 Flexcube reconciliation
      // Mock response
      return {
        matched: 0,
        breaks: [],
      };
    } catch (error) {
      throw new Error(`Reconciliation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }
}

