package com.zioinfo.kintex.visitor;

import com.zioinfo.kintex.visitor.scoring.LeadSignals;
import com.zioinfo.kintex.visitor.scoring.RuleBasedLeadScorer;
import com.zioinfo.kintex.visitor.scoring.ScoreResult;
import org.junit.jupiter.api.Test;

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

/**
 * M10 리드 스코어 규칙 엔진 단위테스트 — 관심도·체류·재방문·결정권자·자료열람 가중 합산의 결정성 검증.
 * 산식(총점 100 = 관심도 40 + 체류 25 + 재방문 20 + 결정권자 10 + 자료 5).
 */
class LeadScoringEngineTest {

    private final RuleBasedLeadScorer scorer = new RuleBasedLeadScorer();

    @Test
    void hotLead_sumsWeightedSignals() {
        // interest 5(=40) + dwell 240%→clamp(round(140*0.25)=35,25)=25 + revisit 2→clamp(16,20)=16
        //   + 결정권자 10 + 자료 2→clamp(10,5)=5 = 96
        ScoreResult r = scorer.score(new LeadSignals(5, 240, 2, true, 2));
        assertEquals(96, r.score());
        assertEquals("rule", r.source());
        assertTrue(r.reasons().stream().anyMatch(s -> s.contains("240%")));
        assertTrue(r.reasons().stream().anyMatch(s -> s.contains("결정권자")));
    }

    @Test
    void coldLead_lowInterestOnly() {
        // interest 1(=8) + dwell 80%→clamp(round(-5),0)=0 + revisit 0 + no dm + no doc = 8
        ScoreResult r = scorer.score(new LeadSignals(1, 80, 0, false, 0));
        assertEquals(8, r.score());
        assertTrue(r.score() >= 0 && r.score() <= 100);
    }

    @Test
    void scoreIsClampedTo100_andMonotonicInInterest() {
        // 모든 신호 최대 → 40+25+20+10+5 = 100, 상한 유지.
        ScoreResult max = scorer.score(new LeadSignals(5, 300, 5, true, 5));
        assertEquals(100, max.score());

        // 관심도 단조 증가(다른 신호 고정): 1점 < 3점 < 5점.
        int s1 = scorer.score(LeadSignals.ofInterest(1)).score();
        int s3 = scorer.score(LeadSignals.ofInterest(3)).score();
        int s5 = scorer.score(LeadSignals.ofInterest(5)).score();
        assertTrue(s1 < s3 && s3 < s5, "관심도가 높을수록 스코어가 높아야 한다");
        assertEquals(8, s1);   // 1*8
        assertEquals(40, s5);  // 5*8
    }

    @Test
    void outOfRangeInterestIsClamped() {
        // interest 0·9 → [1,5] 로 클램프(방어).
        assertEquals(8, scorer.score(new LeadSignals(0, 100, 0, false, 0)).score());
        assertEquals(40, scorer.score(new LeadSignals(9, 100, 0, false, 0)).score());
    }
}
