package com.ga.api.service.regulatory;

import com.ga.common.exception.BizException;
import com.ga.common.exception.ErrorCode;
import com.ga.common.model.PageResponse;
import com.ga.core.mapper.regulatory.RegulatoryLimitMapper;
import com.ga.core.vo.regulatory.RegulatoryLimitResp;
import com.ga.core.vo.regulatory.RegulatoryLimitSaveReq;
import com.ga.core.vo.regulatory.RegulatoryLimitSearchParam;
import com.ga.core.vo.regulatory.RegulatoryLimitVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

@Service
@RequiredArgsConstructor
public class RegulatoryLimitService {

    private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    private final RegulatoryLimitMapper limitMapper;

    @Transactional(readOnly = true)
    public PageResponse<RegulatoryLimitResp> list(RegulatoryLimitSearchParam param) {
        param.startPage();
        return PageResponse.of(limitMapper.selectList(param));
    }

    @Transactional(readOnly = true)
    public RegulatoryLimitResp detail(Long limitId) {
        RegulatoryLimitResp resp = limitMapper.selectDetailById(limitId);
        if (resp == null) {
            throw new BizException(ErrorCode.NOT_FOUND);
        }
        return resp;
    }

    @Transactional
    public void create(RegulatoryLimitSaveReq req) {
        // 동일 limitType + productCategory + 기간 중복 체크
        String today = LocalDate.now().format(DATE_FMT);
        RegulatoryLimitVO existing = limitMapper.selectActiveByType(
                req.getLimitType(), req.getProductCategory(), today);
        if (existing != null) {
            throw new BizException(ErrorCode.DUPLICATE_DATA);
        }

        RegulatoryLimitVO vo = toVO(req);
        vo.setIsActive(true);
        limitMapper.insert(vo);
    }

    @Transactional
    public void update(Long limitId, RegulatoryLimitSaveReq req) {
        RegulatoryLimitVO existing = limitMapper.selectById(limitId);
        if (existing == null) {
            throw new BizException(ErrorCode.NOT_FOUND);
        }

        RegulatoryLimitVO vo = toVO(req);
        vo.setLimitId(limitId);
        vo.setIsActive(existing.getIsActive());
        limitMapper.update(vo);
    }

    @Transactional
    public void deactivate(Long limitId) {
        RegulatoryLimitVO existing = limitMapper.selectById(limitId);
        if (existing == null) {
            throw new BizException(ErrorCode.NOT_FOUND);
        }
        if (Boolean.FALSE.equals(existing.getIsActive())) {
            throw new BizException(ErrorCode.INVALID_PARAMETER);
        }
        limitMapper.updateStatus(limitId, false);
    }

    @Transactional
    public void activate(Long limitId) {
        RegulatoryLimitVO existing = limitMapper.selectById(limitId);
        if (existing == null) {
            throw new BizException(ErrorCode.NOT_FOUND);
        }
        if (Boolean.TRUE.equals(existing.getIsActive())) {
            throw new BizException(ErrorCode.INVALID_PARAMETER);
        }
        String today = LocalDate.now().format(DATE_FMT);
        RegulatoryLimitVO duplicate = limitMapper.selectActiveByType(
                existing.getLimitType(), existing.getProductCategory(), today);
        if (duplicate != null) {
            throw new BizException(ErrorCode.DUPLICATE_DATA);
        }
        limitMapper.updateStatus(limitId, true);
    }

    @Transactional(readOnly = true)
    public RegulatoryLimitVO selectActiveByType(String limitType, String productCategory, String baseDate) {
        return limitMapper.selectActiveByType(limitType, productCategory, baseDate);
    }

    @Transactional(readOnly = true)
    public List<RegulatoryLimitVO> selectAllActive(String baseDate) {
        return limitMapper.selectAllActive(baseDate);
    }

    private RegulatoryLimitVO toVO(RegulatoryLimitSaveReq req) {
        RegulatoryLimitVO vo = new RegulatoryLimitVO();
        vo.setLimitType(req.getLimitType());
        vo.setProductCategory(req.getProductCategory());
        vo.setLimitValue(req.getLimitValue());
        vo.setUnit(req.getUnit());
        vo.setEffectiveFrom(req.getEffectiveFrom());
        vo.setEffectiveTo(req.getEffectiveTo());
        vo.setRegulationRef(req.getRegulationRef());
        vo.setDescription(req.getDescription());
        return vo;
    }
}
