/**
 * Settle Later Tracking Service
 * Monitors and tracks unsettled amounts from Crypto.com OTC T1 settlement
 */

import { CryptoComRestClient } from '../clients/rest-client';
import { UnsettledAmounts, SettleLaterLimit } from '../types';
import { RESPONSE_CODES } from '../config';
import { logger } from '@/infrastructure/monitoring/logger';
import { EventEmitter } from 'events';

export interface UnsettledAlert {
  date: string;
  currency: string;
  amount: string;
  threshold?: number;
}

export interface SettleLaterStatus {
  configuredLimit: string;
  usedLimit: string;
  availableLimit: string;
  unsettledByDate: Record<string, Record<string, string>>;
  alerts: UnsettledAlert[];
}

export class SettleLaterTrackingService extends EventEmitter {
  private restClient: CryptoComRestClient;
  private checkInterval: NodeJS.Timeout | null = null;
  private checkIntervalMs: number = 60000; // 1 minute
  private lastStatus: SettleLaterStatus | null = null;
  private alertThreshold: number = 0.8; // Alert when used > 80% of limit

  constructor(restClient: CryptoComRestClient) {
    super();
    this.restClient = restClient;
  }

  /**
   * Get current settle later status
   */
  async getStatus(): Promise<SettleLaterStatus> {
    const [limitResponse, unsettledResponse] = await Promise.all([
      this.restClient.getSettleLaterLimit(),
      this.restClient.getUnsettledAmounts(),
    ]);

    const limit =
      limitResponse.code === RESPONSE_CODES.SUCCESS
        ? (limitResponse.result as SettleLaterLimit)
        : null;
    const unsettled =
      unsettledResponse.code === RESPONSE_CODES.SUCCESS
        ? (unsettledResponse.result as UnsettledAmounts)
        : null;

    const configuredLimit = limit?.configured_limit ?? '0';
    const usedLimit = limit?.used_limit ?? '0';
    const available = (
      parseFloat(configuredLimit) - parseFloat(usedLimit)
    ).toFixed(2);

    const unsettledByDate = unsettled?.unsettled_ccys ?? {};
    const alerts: UnsettledAlert[] = [];

    if (limit && parseFloat(usedLimit) / parseFloat(configuredLimit) > this.alertThreshold) {
      alerts.push({
        date: new Date().toISOString(),
        currency: 'USD',
        amount: usedLimit,
        threshold: this.alertThreshold * 100,
      });
    }

    for (const [date, amounts] of Object.entries(unsettledByDate)) {
      for (const [currency, amount] of Object.entries(amounts)) {
        const parsed = parseFloat(amount);
        if (Math.abs(parsed) > 1000) {
          alerts.push({ date, currency, amount });
        }
      }
    }

    const status: SettleLaterStatus = {
      configuredLimit,
      usedLimit,
      availableLimit: available,
      unsettledByDate,
      alerts,
    };

    this.lastStatus = status;

    if (alerts.length > 0) {
      this.emit('alerts', alerts);
    }

    return status;
  }

  /**
   * Start periodic monitoring
   */
  startMonitoring(intervalMs?: number): void {
    if (this.checkInterval) {
      this.stopMonitoring();
    }

    this.checkIntervalMs = intervalMs ?? 60000;
    this.checkInterval = setInterval(async () => {
      try {
        const status = await this.getStatus();
        this.emit('status', status);
      } catch (error) {
        logger.error('[SettleLater] Monitoring check failed', {
          error: error instanceof Error ? error.message : String(error),
        });
      }
    }, this.checkIntervalMs);

    logger.info('[SettleLater] Monitoring started', {
      intervalMs: this.checkIntervalMs,
    });
  }

  /**
   * Stop periodic monitoring
   */
  stopMonitoring(): void {
    if (this.checkInterval) {
      clearInterval(this.checkInterval);
      this.checkInterval = null;
      logger.info('[SettleLater] Monitoring stopped');
    }
  }

  /**
   * Get last known status (cached)
   */
  getLastStatus(): SettleLaterStatus | null {
    return this.lastStatus;
  }
}
