package com.zioinfo.kintex.visitor.scoring;

import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 규칙 기반 리드 스코어 엔진(M10 기본). 결정론적·검증 가능한 가중 합산.
 * <p><b>산식(총점 100 = 관심도 40 + 체류 25 + 재방문 20 + 결정권자 10 + 자료열람 5):</b>
 * <ul>
 *   <li>관심도(interest 1~5) × 8 → 8..40</li>
 *   <li>체류: (dwellRatioPct − 100) × 0.25 를 [0,25] 로 클램프(평균 100 → 0, 200% → 25)</li>
 *   <li>재방문: revisitCount × 8 을 [0,20] 로 클램프</li>
 *   <li>결정권자: 10 (해당 시)</li>
 *   <li>자료열람: docDownloads × 5 를 [0,5] 로 클램프</li>
 * </ul>
 * 스코어는 [0,100] 로 최종 클램프한다. AI 연동은 별도 어드바이저가 이 결과를 보정한다.
 */
@Component
public class RuleBasedLeadScorer implements LeadScorer {

    static final int W_INTEREST = 8;   // per interest point (max 40 at interest=5)
    static final int MAX_DWELL = 25;
    static final int MAX_REVISIT = 20;
    static final int W_REVISIT = 8;
    static final int P_DECISION_MAKER = 10;
    static final int MAX_DOC = 5;
    static final int W_DOC = 5;

    @Override
    public ScoreResult score(LeadSignals s) {
        List<String> reasons = new ArrayList<>();

        int interest = clamp(s.interest(), 1, 5);
        int interestPts = interest * W_INTEREST;
        if (interest >= 4) {
            reasons.add("상담원 관심도 " + interest + "점(상)으로 구매 의향 높음");
        } else if (interest >= 3) {
            reasons.add("상담원 관심도 " + interest + "점(중)");
        }

        int dwellPts = clamp((int) Math.round((s.dwellRatioPct() - 100) * 0.25), 0, MAX_DWELL);
        if (s.dwellRatioPct() >= 150) {
            reasons.add("부스 체류 시간 평균 대비 " + s.dwellRatioPct() + "%");
        }

        int revisitPts = clamp(s.revisitCount() * W_REVISIT, 0, MAX_REVISIT);
        if (s.revisitCount() >= 1) {
            reasons.add("부스 재방문 " + s.revisitCount() + "회");
        }

        int dmPts = s.decisionMaker() ? P_DECISION_MAKER : 0;
        if (s.decisionMaker()) {
            reasons.add("구매 결정권자 직급으로 확인");
        }

        int docPts = clamp(s.docDownloads() * W_DOC, 0, MAX_DOC);
        if (s.docDownloads() >= 1) {
            reasons.add("기술 자료 열람/다운로드 " + s.docDownloads() + "건");
        }

        int score = clamp(interestPts + dwellPts + revisitPts + dmPts + docPts, 0, 100);
        if (reasons.isEmpty()) {
            reasons.add("기본 관심도 기반 스코어");
        }
        return new ScoreResult(score, reasons, "rule");
    }

    private static int clamp(int v, int min, int max) {
        return Math.max(min, Math.min(v, max));
    }
}
