import { Inject, Injectable, Logger, NotFoundException } from '@nestjs/common';
import { AlertStatus } from '../../domain/entities/aml-alert.entity';
import {
  AML_ALERT_REPOSITORY,
  IAmlAlertRepository,
} from '../../domain/repositories/aml-alert.repository.interface';
import {
  OFAC_SCREENING_REPOSITORY,
  IOfacScreeningRepository,
} from '../../domain/repositories/ofac-screening.repository.interface';
import {
  SAR_REPORT_REPOSITORY,
  ISarReportRepository,
} from '../../domain/repositories/sar-report.repository.interface';
import {
  AUDIT_LOGGER_SERVICE,
  IAuditLoggerService,
} from '../../domain/ports/audit-logger.interface';

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

  constructor(
    @Inject(AML_ALERT_REPOSITORY)
    private readonly alertRepo: IAmlAlertRepository,
    @Inject(OFAC_SCREENING_REPOSITORY)
    private readonly ofacRepo: IOfacScreeningRepository,
    @Inject(SAR_REPORT_REPOSITORY)
    private readonly sarRepo: ISarReportRepository,
    @Inject(AUDIT_LOGGER_SERVICE)
    private readonly auditLogger: IAuditLoggerService,
  ) {}

  /** Risk dashboard: aggregate stats across alerts, screenings, SARs */
  async getDashboard() {
    const [activeAlerts, suspiciousTradesCount, frozenAccountsCount] = await Promise.all([
      this.alertRepo.count({
        where: [
          { status: AlertStatus.OPEN },
          { status: AlertStatus.INVESTIGATING },
          { status: AlertStatus.ESCALATED },
        ],
      }),
      this.alertRepo.countHighRiskActive(70),
      this.ofacRepo.count({ where: { isMatch: true } }),
    ]);

    const recentAlerts = await this.alertRepo.find({
      order: { createdAt: 'DESC' },
      take: 5,
    });

    return {
      activeAlerts,
      suspiciousTradesCount,
      frozenAccountsCount,
      recentAlerts,
    };
  }

  /** List active risk/AML alerts (paginated) */
  async listAlerts(page: number, limit: number, status?: string, pattern?: string) {
    const [items, total] = await this.alertRepo.findPaginated(page, limit, { status, pattern });
    return { items, total, page, limit, totalPages: Math.ceil(total / limit) };
  }

  /** List flagged suspicious transactions (high risk score) */
  async listSuspiciousTrades(page: number, limit: number) {
    const [items, total] = await this.alertRepo.findSuspicious(page, limit, 70);
    return { items, total, page, limit, totalPages: Math.ceil(total / limit) };
  }

  /** List blacklisted users from OFAC screening */
  async listBlacklist(page: number, limit: number) {
    const [items, total] = await this.ofacRepo.findMatchesPaginated(page, limit);
    return { items, total, page, limit, totalPages: Math.ceil(total / limit) };
  }

  /** Freeze account: escalate alert and log action */
  async freezeAccount(
    alertId: string,
    adminId: string,
    adminName: string,
    ipAddress?: string,
  ) {
    const alert = await this.alertRepo.findById(alertId);
    if (!alert) throw new NotFoundException('Alert not found');

    const previousStatus = alert.status;
    alert.status = AlertStatus.ESCALATED;
    alert.resolution = `Account frozen by admin ${adminName}`;
    await this.alertRepo.save(alert);

    // Log the admin action via shared service
    await this.auditLogger.log({
      adminId,
      adminName,
      action: 'freeze_account',
      resource: 'aml_alert',
      resourceId: alertId,
      ipAddress,
      details: {
        userId: alert.userId,
        previousStatus,
      },
    });

    this.logger.warn(`Account frozen: alert=${alertId}, user=${alert.userId}, by admin=${adminId}`);
    return { alertId, userId: alert.userId, status: 'frozen' };
  }

  /** Generate a SAR from a suspicious alert */
  async generateSar(
    alertId: string,
    adminId: string,
    adminName: string,
    ipAddress?: string,
  ) {
    const alert = await this.alertRepo.findById(alertId);
    if (!alert) throw new NotFoundException('Alert not found');

    const sar = this.sarRepo.create({
      alertId: alert.id,
      userId: alert.userId,
      reportType: 'suspicious_activity',
      narrative: `Auto-generated SAR from AML alert: ${alert.description}. Pattern: ${alert.pattern}, Risk Score: ${alert.riskScore}`,
      filingStatus: 'draft',
    });
    const saved = await this.sarRepo.save(sar);

    // Update alert status
    alert.status = AlertStatus.ESCALATED;
    await this.alertRepo.save(alert);

    // Log the admin action via shared service
    await this.auditLogger.log({
      adminId,
      adminName,
      action: 'generate_sar',
      resource: 'sar_report',
      resourceId: saved.id,
      ipAddress,
      details: {
        alertId,
        userId: alert.userId,
      },
    });

    this.logger.log(`SAR generated: sar=${saved.id} from alert=${alertId}, by admin=${adminId}`);
    return saved;
  }
}
