package com.zioinfo.kintex.rules;

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;

/**
 * 룰셋 데이터 로더 — 기동 시 규정·요율 JSON을 메모리에 적재한다.
 * 룰셋은 버전 관리되는 데이터이므로 교체(규정 개정) 시 코드 변경 없이 리소스만 갱신한다.
 * (Phase 2: DB 기반 버전 테이블 + 핫리로드로 확장 가능 — 현재는 classpath 리소스 로딩 구조만.)
 */
@Component
public class RuleSetLoader {

    private static final Logger log = LoggerFactory.getLogger(RuleSetLoader.class);

    private final RuleProperties props;
    private final ObjectMapper objectMapper;

    private volatile ComplianceRuleSet compliance;
    private volatile RateRuleSet rates;

    public RuleSetLoader(RuleProperties props, ObjectMapper objectMapper) {
        this.props = props;
        this.objectMapper = objectMapper;
    }

    @PostConstruct
    public void load() {
        this.compliance = read(props.getComplianceRuleset(), ComplianceRuleSet.class, "compliance");
        this.rates = read(props.getRateRuleset(), RateRuleSet.class, "rate");
        if (compliance != null) {
            log.info("규정 룰셋 로드: {} (규칙 {}개)", compliance.rulesetVersion(),
                    compliance.rules() == null ? 0 : compliance.rules().size());
        }
        if (rates != null) {
            log.info("요율 룰셋 로드: {}", rates.rulesetVersion());
        }
    }

    private <T> T read(Resource resource, Class<T> type, String kind) {
        if (resource == null) {
            log.warn("{} 룰셋 리소스가 설정되지 않았습니다.", kind);
            return null;
        }
        try (InputStream in = resource.getInputStream()) {
            return objectMapper.readValue(in, type);
        } catch (IOException e) {
            // 룰셋 로드 실패는 기동을 막지 않되(운영 안전), 명확히 경고. 사용 시점에 null 가드.
            log.error("{} 룰셋 로드 실패: {}", kind, e.getMessage());
            return null;
        }
    }

    public ComplianceRuleSet compliance() {
        return compliance;
    }

    public RateRuleSet rates() {
        return rates;
    }
}
