package com.zioinfo.kintex.auction;

import com.zioinfo.kintex.auction.dto.AuctionDtos.Weights;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
 * M15 낙찰 종합점수 산식 단위테스트 — 가격·평판·납기 정규화 가중합(SCR-29 비교표 스코어).
 * 최저가·최단납기·최고평판이 각 축 100점이며, comprehensive 는 가중 평균·lowest 는 가격만 사용함을 고정.
 */
class AuctionScoringTest {

    @Test
    void lowestCriteria_usesPriceScoreOnly() {
        Weights w = new Weights(60, 25, 15); // lowest 에선 가중치 무시
        // 최저가(8.4M)=100점, 8.7M=8.4/8.7*100=96.6
        assertEquals(100.0, AuctionScoring.score("lowest", w, 8_400_000L, 8_400_000L, 12, 10, 4.8), 1e-9);
        assertEquals(96.6, AuctionScoring.score("lowest", w, 8_700_000L, 8_400_000L, 10, 10, 4.6), 1e-9);
    }

    @Test
    void comprehensive_weightedAverageOfNormalizedAxes() {
        Weights w = new Weights(60, 25, 15);
        // 업체 A: 최저가 8.4M(가격 100), 평판 4.8(=96), 납기 12일(최단 10 → 83.3)
        //   score = (100*60 + 96*25 + 83.3*15)/100 = (6000 + 2400 + 1249.5)/100 = 96.495 → 96.5
        double a = AuctionScoring.score("comprehensive", w, 8_400_000L, 8_400_000L, 12, 10, 4.8);
        assertEquals(96.5, a, 1e-9);

        // 업체 B: 8.7M(가격 96.55), 평판 4.6(=92), 납기 10일 최단(100)
        //   score = (96.5517*60 + 92*25 + 100*15)/100 = (5793.10 + 2300 + 1500)/100 = 95.931 → 95.9
        double b = AuctionScoring.score("comprehensive", w, 8_700_000L, 8_400_000L, 10, 10, 4.6);
        assertEquals(95.9, b, 1e-9);

        assertTrue(a > b, "최저가+최고평판 업체 A 가 종합 우위여야 한다");
    }

    @Test
    void zeroWeights_doNotDivideByZero() {
        Weights w = new Weights(0, 0, 0);
        double s = AuctionScoring.score("comprehensive", w, 5_000_000L, 5_000_000L, 8, 8, 4.0);
        assertTrue(s >= 0.0 && s <= 100.0);
    }

    @Test
    void axisScores_bounded0to100() {
        assertEquals(100.0, AuctionScoring.priceScore(1000L, 1000L), 1e-9);
        assertTrue(AuctionScoring.priceScore(2000L, 1000L) < 100.0);
        assertEquals(100.0, AuctionScoring.reputationScore(5.0), 1e-9);
        assertEquals(80.0, AuctionScoring.reputationScore(4.0), 1e-9);
        assertEquals(100.0, AuctionScoring.deliveryScore(10, 10), 1e-9);
        assertTrue(AuctionScoring.deliveryScore(20, 10) < 100.0);
    }
}
