package com.zioinfo.kintex.auction;

import com.zioinfo.kintex.auction.dto.AuctionDtos.Weights;

/**
 * 낙찰 종합점수 산식(순수 함수 — 단위 테스트 대상).
 *
 * <p>세 축을 0~100 으로 정규화한 뒤 가중 평균한다. 모두 <b>높을수록 우수</b>:
 * <ul>
 *   <li><b>가격</b>: minTotal/total × 100 — 최저가가 100점, 비쌀수록 감점.</li>
 *   <li><b>평판</b>: rating/5 × 100 — 5점 만점 평점.</li>
 *   <li><b>납기</b>: minLead/lead × 100 — 가장 빠른 납기가 100점.</li>
 * </ul>
 * 낙찰기준 {@code lowest}는 가격 점수만 사용, {@code comprehensive}는 가중 평균.
 * 가중치 합이 0이면 분모를 1로 보정한다.
 */
public final class AuctionScoring {

    private AuctionScoring() {
    }

    public static double priceScore(long total, long minTotal) {
        if (total <= 0) return 0.0;
        return minTotal > 0 ? (double) minTotal / total * 100.0 : 100.0;
    }

    public static double reputationScore(double rating) {
        double clamped = Math.max(0.0, Math.min(rating, 5.0));
        return clamped / 5.0 * 100.0;
    }

    public static double deliveryScore(int lead, int minLead) {
        return lead > 0 && minLead > 0 ? (double) minLead / lead * 100.0 : 100.0;
    }

    /** 종합점수(소수 1자리 반올림). */
    public static double score(String criteria, Weights w,
                               long total, long minTotal, int lead, int minLead, double rating) {
        double price = priceScore(total, minTotal);
        if ("lowest".equals(criteria)) {
            return round1(price);
        }
        double rep = reputationScore(rating);
        double delivery = deliveryScore(lead, minLead);
        int denom = Math.max(w.price() + w.reputation() + w.delivery(), 1);
        double weighted = (price * w.price() + rep * w.reputation() + delivery * w.delivery()) / denom;
        return round1(weighted);
    }

    public static double round1(double v) {
        return Math.round(v * 10.0) / 10.0;
    }
}
