import { Inject, Injectable, Logger } from '@nestjs/common';
import { AmlAlert, AmlPattern, AlertStatus } from '../../domain/entities/aml-alert.entity';
import {
  AML_ALERT_REPOSITORY,
  IAmlAlertRepository,
} from '../../domain/repositories/aml-alert.repository.interface';
import { RiskScore } from '../../domain/value-objects/risk-score.vo';
import { AlertSeverity } from '../../domain/value-objects/alert-severity.vo';

@Injectable()
export class AmlService {
  private readonly logger = new Logger('AMLService');

  constructor(
    @Inject(AML_ALERT_REPOSITORY)
    private readonly repo: IAmlAlertRepository,
  ) {}

  /**
   * Analyze a transaction for AML patterns.
   * 5 patterns: buy-transfer-withdraw, fan-out, self-dealing, cross-border, structuring
   */
  async analyzeTransaction(data: {
    userId: string;
    type: string;
    amount: number;
    recipientId?: string;
    metadata?: any;
  }): Promise<AmlAlert[]> {
    const alerts: AmlAlert[] = [];

    // Pattern 1: Structuring - multiple transactions just below $3,000 threshold
    if (data.amount >= 2500 && data.amount < 3000) {
      alerts.push(
        await this.createAlert(
          data.userId,
          AmlPattern.STRUCTURING,
          60,
          `Transaction of $${data.amount} near $3,000 threshold`,
          { amount: data.amount },
        ),
      );
    }

    // Pattern 2: Large transaction threshold ($10,000+)
    if (data.amount >= 10000) {
      alerts.push(
        await this.createAlert(
          data.userId,
          AmlPattern.CROSS_BORDER,
          80,
          `Large transaction: $${data.amount}`,
          { amount: data.amount },
        ),
      );
    }

    // Pattern 3: Self-dealing detection
    if (data.recipientId === data.userId) {
      alerts.push(
        await this.createAlert(
          data.userId,
          AmlPattern.SELF_DEALING,
          90,
          'Self-dealing detected: sender equals recipient',
          { recipientId: data.recipientId },
        ),
      );
    }

    return alerts;
  }

  async createAlert(
    userId: string,
    pattern: AmlPattern,
    riskScore: number,
    description: string,
    evidence: any,
  ): Promise<AmlAlert> {
    const score = RiskScore.create(riskScore);
    const severity = AlertSeverity.fromRiskScore(riskScore);

    const alert = this.repo.create({
      userId,
      pattern,
      riskScore: score.toString(),
      description,
      evidence,
      status: AlertStatus.OPEN,
    });
    this.logger.warn(
      `AML Alert: ${pattern} for user ${userId}, risk=${score.value}, severity=${severity.value}`,
    );
    return this.repo.save(alert);
  }

  async listAlerts(page: number, limit: number, status?: string) {
    const where = status ? { status: status as any } : {};
    const [items, total] = await this.repo.findAndCount({
      where,
      skip: (page - 1) * limit,
      take: limit,
      order: { createdAt: 'DESC' },
    });
    return { items, total, page, limit };
  }

  async updateAlertStatus(id: string, status: AlertStatus, resolution?: string) {
    await this.repo.update(id, { status, resolution: resolution || null });
  }
}
