import { Injectable, Inject } from '@nestjs/common';
import { BreakageRecord } from '../../domain/entities/breakage-record.entity';
import {
  BREAKAGE_REPOSITORY,
  IBreakageRepository,
} from '../../domain/repositories/breakage.repository.interface';
import { BreakageRate } from '../../domain/value-objects/breakage-rate.vo';
import { SettlementAmount } from '../../domain/value-objects/settlement-amount.vo';

@Injectable()
export class BreakageService {
  constructor(
    @Inject(BREAKAGE_REPOSITORY)
    private readonly breakageRepo: IBreakageRepository,
  ) {}

  /**
   * Pure domain calculation: compute breakage amount and rate.
   * This logic belongs in the domain layer and uses Value Objects for validation.
   */
  calculateBreakage(
    totalIssued: number,
    totalRedeemed: number,
    faceValue: number,
  ): { breakageAmount: SettlementAmount; breakageRate: BreakageRate } {
    const totalExpired = totalIssued - totalRedeemed;
    const breakageRate = BreakageRate.calculate(totalIssued, totalRedeemed);
    const breakageAmount = SettlementAmount.create(String(totalExpired * faceValue));
    return { breakageAmount, breakageRate };
  }

  async recordBreakage(data: {
    couponId: string;
    issuerId: string;
    totalIssued: number;
    totalRedeemed: number;
    totalExpired: number;
    faceValue: number;
  }): Promise<BreakageRecord> {
    const { breakageAmount, breakageRate } = this.calculateBreakage(
      data.totalIssued,
      data.totalRedeemed,
      data.faceValue,
    );

    const record = this.breakageRepo.create({
      couponId: data.couponId,
      issuerId: data.issuerId,
      totalIssued: data.totalIssued,
      totalRedeemed: data.totalRedeemed,
      totalExpired: data.totalExpired,
      breakageAmount: breakageAmount.value,
      breakageRate: breakageRate.value,
    });

    return this.breakageRepo.save(record);
  }

  async getByIssuerId(issuerId: string): Promise<BreakageRecord[]> {
    return this.breakageRepo.findByIssuerId(issuerId);
  }
}
