import { QualityScoreCalculator } from '../services/quality-score.service';

describe('QualityScoreCalculator', () => {
  it('calculates score with all inputs at maximum', () => {
    const score = QualityScoreCalculator.calculate({
      avgRating: 5,
      totalReviews: 10,
      responseTimeAvg: 0,
      conversionRate: 1,
      activeListingRatio: 1,
    });

    // rating: (5/5)*100*0.4 = 40, response: 100*0.3 = 30, conversion: 100*0.2 = 20, listing: 100*0.1 = 10
    expect(score).toBe(100);
  });

  it('calculates score with mixed inputs', () => {
    const score = QualityScoreCalculator.calculate({
      avgRating: 4,
      totalReviews: 5,
      responseTimeAvg: 1800, // 30 minutes
      conversionRate: 0.3,
      activeListingRatio: 0.5,
    });

    // rating: (4/5)*100*0.4 = 32
    // response: max(0, 100 - (1800/3600)*100)*0.3 = 50*0.3 = 15
    // conversion: 30*0.2 = 6
    // listing: 50*0.1 = 5
    // total = 58
    expect(score).toBe(58);
  });

  it('defaults rating score to 50 with no reviews', () => {
    const score = QualityScoreCalculator.calculate({
      avgRating: 0,
      totalReviews: 0,
      responseTimeAvg: 0,
      conversionRate: 0,
      activeListingRatio: 0,
    });

    // rating: 50*0.4 = 20, response: 100*0.3 = 30, conversion: 0, listing: 0
    expect(score).toBe(50);
  });

  it('defaults response score to 50 with null response time', () => {
    const score = QualityScoreCalculator.calculate({
      avgRating: 0,
      totalReviews: 0,
      responseTimeAvg: null,
      conversionRate: 0,
      activeListingRatio: 0,
    });

    // rating: 50*0.4 = 20, response: 50*0.3 = 15, conversion: 0, listing: 0
    expect(score).toBe(35);
  });

  it('clamps response score to 0 when response time >= 1 hour', () => {
    const score = QualityScoreCalculator.calculate({
      avgRating: 5,
      totalReviews: 1,
      responseTimeAvg: 3600, // exactly 1 hour
      conversionRate: 0,
      activeListingRatio: 0,
    });

    // rating: 100*0.4 = 40, response: max(0, 100-100)*0.3 = 0, conversion: 0, listing: 0
    expect(score).toBe(40);
  });

  it('clamps response score to 0 when response time > 1 hour', () => {
    const score = QualityScoreCalculator.calculate({
      avgRating: 5,
      totalReviews: 1,
      responseTimeAvg: 7200, // 2 hours
      conversionRate: 0,
      activeListingRatio: 0,
    });

    // rating: 100*0.4 = 40, response: max(0, 100-200)*0.3 = 0, conversion: 0, listing: 0
    expect(score).toBe(40);
  });

  it('returns score with 1 decimal precision', () => {
    const score = QualityScoreCalculator.calculate({
      avgRating: 3.7,
      totalReviews: 3,
      responseTimeAvg: 600, // 10 min
      conversionRate: 0.15,
      activeListingRatio: 0.33,
    });

    // Verify it has at most 1 decimal place
    const decimalPart = score.toString().split('.')[1];
    expect(!decimalPart || decimalPart.length <= 1).toBe(true);
  });

  it('score is bounded 0-100', () => {
    // All zeros (except default for 0 reviews)
    const minScore = QualityScoreCalculator.calculate({
      avgRating: 0,
      totalReviews: 1, // force avgRating to be used as 0
      responseTimeAvg: 99999,
      conversionRate: 0,
      activeListingRatio: 0,
    });

    expect(minScore).toBeGreaterThanOrEqual(0);

    const maxScore = QualityScoreCalculator.calculate({
      avgRating: 5,
      totalReviews: 100,
      responseTimeAvg: 0,
      conversionRate: 1,
      activeListingRatio: 1,
    });

    expect(maxScore).toBeLessThanOrEqual(100);
  });
});
