/**
 * Credit Score Result Value Object
 *
 * Encapsulates a credit score with its contributing factors and risk level.
 * Immutable once created; all validation happens at construction time.
 */
export class CreditScoreResult {
  readonly score: number;
  readonly level: CreditLevel;
  readonly factors: CreditScoreFactors;
  readonly recommendations: string[];

  private constructor(props: {
    score: number;
    level: CreditLevel;
    factors: CreditScoreFactors;
    recommendations: string[];
  }) {
    this.score = props.score;
    this.level = props.level;
    this.factors = props.factors;
    this.recommendations = props.recommendations;
  }

  /**
   * Create a CreditScoreResult from raw factor values.
   * Applies weighting: redemption 35%, breakage 25%, tenure 20%, satisfaction 20%.
   */
  static fromFactors(params: {
    redemptionRate: number;
    breakageRate: number;
    tenureDays: number;
    satisfactionScore: number;
  }): CreditScoreResult {
    const r = Math.min(100, params.redemptionRate * 100) * 0.35;
    const b = Math.min(100, (1 - params.breakageRate) * 100) * 0.25;
    const t = Math.min(100, (params.tenureDays / 365) * 100) * 0.20;
    const s = Math.min(100, params.satisfactionScore) * 0.20;
    const score = Math.round(r + b + t + s);
    const level = CreditScoreResult.scoreToLevel(score);

    return new CreditScoreResult({
      score,
      level,
      factors: { redemption: r, breakage: b, tenure: t, satisfaction: s },
      recommendations: [],
    });
  }

  /**
   * Reconstitute from external AI agent response data.
   */
  static fromResponse(data: {
    score: number;
    level: string;
    factors: Record<string, number>;
    recommendations?: string[];
  }): CreditScoreResult {
    return new CreditScoreResult({
      score: data.score,
      level: (data.level as CreditLevel) || CreditScoreResult.scoreToLevel(data.score),
      factors: {
        redemption: data.factors.redemption ?? 0,
        breakage: data.factors.breakage ?? 0,
        tenure: data.factors.tenure ?? 0,
        satisfaction: data.factors.satisfaction ?? 0,
      },
      recommendations: data.recommendations ?? [],
    });
  }

  private static scoreToLevel(score: number): CreditLevel {
    if (score >= 80) return 'A';
    if (score >= 60) return 'B';
    if (score >= 40) return 'C';
    if (score >= 20) return 'D';
    return 'F';
  }

  toPlain(): {
    score: number;
    level: string;
    factors: Record<string, number>;
    recommendations: string[];
  } {
    return {
      score: this.score,
      level: this.level,
      factors: { ...this.factors },
      recommendations: [...this.recommendations],
    };
  }
}

export type CreditLevel = 'A' | 'B' | 'C' | 'D' | 'F';

export interface CreditScoreFactors {
  redemption: number;
  breakage: number;
  tenure: number;
  satisfaction: number;
}
