package com.ga.api.service.kpi;

import com.ga.common.exception.BizException;
import com.ga.common.exception.ErrorCode;
import com.ga.common.model.PageResponse;
import com.ga.core.mapper.kpi.ForecastKpiMonthlyMapper;
import com.ga.core.vo.kpi.ForecastKpiMonthlyResp;
import com.ga.core.vo.kpi.ForecastKpiMonthlySaveReq;
import com.ga.core.vo.kpi.ForecastKpiMonthlySearchParam;
import com.ga.core.vo.kpi.ForecastKpiMonthlyVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Set;

@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ForecastKpiMonthlyService {

    private static final Map<String, Integer> SAMPLE_SIZE = Map.of(
            "SMA3", 3,
            "SMA6", 6,
            "NAIVE", 1
    );

    private final ForecastKpiMonthlyMapper mapper;

    public PageResponse<ForecastKpiMonthlyResp> list(ForecastKpiMonthlySearchParam param) {
        param.startPage();
        return PageResponse.of(mapper.selectList(param));
    }

    /**
     * 차월 예측 재산출. forecastMonth 기준 직전 N개월 평균/표준편차 → 4 metric UPSERT.
     */
    @Transactional
    public int regenerate(ForecastKpiMonthlySaveReq req) {
        if (req.getForecastMonth() == null || req.getForecastMonth().isBlank()) {
            throw new BizException(ErrorCode.INVALID_PARAMETER);
        }
        String method = req.getMethod() == null ? "SMA3" : req.getMethod();
        Integer sampleSize = SAMPLE_SIZE.get(method);
        if (sampleSize == null) throw new BizException(ErrorCode.INVALID_PARAMETER);

        List<ForecastKpiMonthlyVO> rows = mapper.computeForecast(req.getForecastMonth(), method, sampleSize);
        if (rows.isEmpty()) {
            log.info("[ForecastKpi] no input data for forecastMonth={}", req.getForecastMonth());
            return 0;
        }
        int n = mapper.upsertBatch(rows);
        log.info("[ForecastKpi] forecastMonth={} method={} sample={} rows={}",
                req.getForecastMonth(), method, sampleSize, n);
        return n;
    }
}
