import { Injectable, Inject, NotFoundException } from '@nestjs/common';
import { ISSUER_REPOSITORY, IIssuerRepository } from '../../domain/repositories/issuer.repository.interface';
import { COUPON_REPOSITORY, ICouponRepository } from '../../domain/repositories/coupon.repository.interface';
import { CREDIT_METRIC_REPOSITORY, ICreditMetricRepository } from '../../domain/repositories/credit-metric.repository.interface';
import { CouponStatus } from '../../domain/entities/coupon.entity';
import { CreditScoringService } from './credit-scoring.service';

@Injectable()
export class IssuerStatsService {
  constructor(
    @Inject(ISSUER_REPOSITORY)
    private readonly issuerRepo: IIssuerRepository,
    @Inject(COUPON_REPOSITORY)
    private readonly couponRepo: ICouponRepository,
    @Inject(CREDIT_METRIC_REPOSITORY)
    private readonly creditMetricRepo: ICreditMetricRepository,
    private readonly creditScoringService: CreditScoringService,
  ) {}

  async getDashboardStats(issuerId: string) {
    const issuer = await this.issuerRepo.findById(issuerId);
    if (!issuer) throw new NotFoundException('Issuer not found');

    // Aggregate coupon stats for this issuer
    const [coupons, total] = await this.couponRepo.findAndCount({
      issuerId,
      page: 1,
      limit: 1,
    });

    const issuedCount = total;

    // Count redeemed coupons
    const [, redeemedCount] = await this.couponRepo.findAndCount({
      issuerId,
      status: CouponStatus.REDEEMED,
      page: 1,
      limit: 1,
    });

    const redemptionRate = issuedCount > 0
      ? Math.round((redeemedCount / issuedCount) * 10000) / 10000
      : 0;

    // Get total revenue: sum of current_price for sold/redeemed coupons
    const [soldCoupons] = await this.couponRepo.findAndCount({
      issuerId,
      status: CouponStatus.SOLD,
      page: 1,
      limit: 100000,
    });
    const [redeemedCoupons] = await this.couponRepo.findAndCount({
      issuerId,
      status: CouponStatus.REDEEMED,
      page: 1,
      limit: 100000,
    });

    const allRevenueCoupons = [...soldCoupons, ...redeemedCoupons];
    const totalRevenue = allRevenueCoupons.reduce(
      (sum, c) => sum + (Number(c.currentPrice) || 0),
      0,
    );

    const creditScore = Number(issuer.creditScore) || 50;

    return {
      issuedCount,
      redemptionRate,
      totalRevenue: Math.round(totalRevenue * 100) / 100,
      creditScore,
      quotaUsed: issuedCount,
      quotaTotal: 10000, // configurable limit
    };
  }

  async getCreditDetails(issuerId: string) {
    const issuer = await this.issuerRepo.findById(issuerId);
    if (!issuer) throw new NotFoundException('Issuer not found');

    const latestMetric = await this.creditMetricRepo.findLatestByIssuerId(issuerId);
    const numericScore = Number(issuer.creditScore) || 50;

    // Derive grade from score
    const grade = numericScore >= 90 ? 'AA' :
                  numericScore >= 80 ? 'A+' :
                  numericScore >= 70 ? 'A' :
                  numericScore >= 60 ? 'B+' :
                  numericScore >= 50 ? 'B' :
                  numericScore >= 40 ? 'C+' :
                  numericScore >= 30 ? 'C' : 'D';

    const tier = numericScore >= 80 ? 'premium' :
                 numericScore >= 60 ? 'standard' :
                 numericScore >= 40 ? 'basic' : 'probation';

    const factors = latestMetric ? {
      redemptionRate: { weight: 0.35, score: Number(latestMetric.redemptionRate) * 100 },
      breakageRate: { weight: 0.25, score: (1 - Number(latestMetric.breakageRate)) * 100 },
      tenure: { weight: 0.20, score: Math.min(100, (latestMetric.tenureDays / 365) * 100) },
      satisfaction: { weight: 0.20, score: Number(latestMetric.satisfactionScore) },
    } : {
      redemptionRate: { weight: 0.35, score: 0 },
      breakageRate: { weight: 0.25, score: 0 },
      tenure: { weight: 0.20, score: 0 },
      satisfaction: { weight: 0.20, score: 0 },
    };

    const suggestions: string[] = [];
    if (factors.redemptionRate.score < 50) suggestions.push('Improve coupon redemption rates by promoting usage');
    if (factors.satisfaction.score < 50) suggestions.push('Enhance customer satisfaction through better service');
    if (factors.tenure.score < 50) suggestions.push('Maintain consistent platform activity to build tenure');

    return {
      grade,
      numericScore,
      factors,
      tier,
      suggestions,
      lastCalculatedAt: latestMetric?.calculatedAt || null,
    };
  }
}
