// Fees & Pricing Engine
// Manages fee schedules, interchange sharing, and tiered pricing

import { Decimal } from '@prisma/client/runtime/library';
import { DbisError, ErrorCode } from '@/shared/types';
import { logger } from '@/infrastructure/monitoring/logger';

export interface FeeSchedule {
  id: string;
  name: string;
  feeType: 'percentage' | 'fixed' | 'tiered';
  percentage?: number;
  fixedAmount?: string;
  tiers?: Array<{
    min: string;
    max?: string;
    fee: string;
  }>;
  currencyCode: string;
  effectiveFrom: Date;
  effectiveTo?: Date;
}

export interface CalculateFeeRequest {
  amount: string;
  currencyCode: string;
  feeScheduleId?: string;
  feeType?: 'percentage' | 'fixed' | 'tiered';
  percentage?: number;
  fixedAmount?: string;
  interchangeShare?: number; // Percentage of interchange to share
}

export interface FeeCalculation {
  baseAmount: string;
  feeAmount: string;
  netAmount: string;
  feeBreakdown: {
    baseFee: string;
    interchangeShare?: string;
    totalFee: string;
  };
}

export class FeesService {
  /**
   * Calculate fees for a transaction
   */
  async calculateFee(request: CalculateFeeRequest): Promise<FeeCalculation> {
    const amount = new Decimal(request.amount);
    let feeAmount = new Decimal(0);

    // Calculate base fee
    if (request.feeType === 'percentage' && request.percentage) {
      feeAmount = amount.times(new Decimal(request.percentage).div(100));
    } else if (request.feeType === 'fixed' && request.fixedAmount) {
      feeAmount = new Decimal(request.fixedAmount);
    } else {
      // Default: 2.9% + $0.30 (common payment processor fee)
      feeAmount = amount.times(new Decimal('0.029')).plus(new Decimal('0.30'));
    }

    // Calculate interchange share if applicable
    let interchangeShare: Decimal | undefined;
    if (request.interchangeShare) {
      interchangeShare = feeAmount.times(new Decimal(request.interchangeShare).div(100));
    }

    const totalFee = interchangeShare
      ? feeAmount.minus(interchangeShare)
      : feeAmount;

    const netAmount = amount.minus(totalFee);

    logger.info(`Fee calculated`, {
      baseAmount: amount.toString(),
      feeAmount: totalFee.toString(),
      netAmount: netAmount.toString(),
    });

    return {
      baseAmount: amount.toString(),
      feeAmount: totalFee.toString(),
      netAmount: netAmount.toString(),
      feeBreakdown: {
        baseFee: feeAmount.toString(),
        interchangeShare: interchangeShare?.toString(),
        totalFee: totalFee.toString(),
      },
    };
  }

  /**
   * Get fee schedule
   */
  async getFeeSchedule(scheduleId: string): Promise<FeeSchedule | null> {
    // In production, fetch from database
    // For now, return null
    return null;
  }
}

export const feesService = new FeesService();
