package com.yhy.module.core.service.calcbaserate.impl;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.yhy.module.core.enums.ErrorCodeConstants.CALC_BASE_RATE_ITEM_NOT_EXISTS;

import cn.hutool.core.collection.CollUtil;
import com.yhy.module.core.controller.admin.calcbaserate.vo.CalcBaseRateItemRespVO;
import com.yhy.module.core.controller.admin.calcbaserate.vo.CalcBaseRateItemSaveReqVO;
import com.yhy.module.core.dal.dataobject.calcbaserate.CalcBaseRateItemDO;
import com.yhy.module.core.dal.mysql.calcbaserate.CalcBaseRateItemMapper;
import com.yhy.module.core.service.calcbaserate.CalcBaseRateItemService;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

/**
 * 基数费率项 Service 实现类
 *
 * @author yhy
 */
@Service
@Validated
@Slf4j
public class CalcBaseRateItemServiceImpl implements CalcBaseRateItemService {

    @Resource
    private CalcBaseRateItemMapper calcBaseRateItemMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createCalcBaseRateItem(CalcBaseRateItemSaveReqVO createReqVO) {
        // 1. 构建DO对象
        CalcBaseRateItemDO item = buildCalcBaseRateItemDO(createReqVO);

        // 2. 设置排序：如果指定了 sortOrder，先将 >= 该值的现有记录 +1（实现"上方/下方插入"）
        if (item.getSortOrder() != null) {
            calcBaseRateItemMapper.shiftSortOrder(createReqVO.getCalcBaseRateDirectoryId(), item.getSortOrder());
        } else {
            item.setSortOrder(getNextSortOrder(createReqVO.getCalcBaseRateDirectoryId()));
        }

        // 3. 插入数据库
        calcBaseRateItemMapper.insert(item);

        return item.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCalcBaseRateItem(CalcBaseRateItemSaveReqVO updateReqVO) {
        // 1. 校验存在
        validateCalcBaseRateItemExists(updateReqVO.getId());

        // 2. 构建更新对象
        CalcBaseRateItemDO updateObj = CalcBaseRateItemDO.builder()
                .id(updateReqVO.getId())
                .name(updateReqVO.getName())
                .rate(updateReqVO.getRate())
                .remark(updateReqVO.getRemark())
                .sortOrder(updateReqVO.getSortOrder())
                .attributes(updateReqVO.getAttributes())
                .build();

        // 3. 更新数据库
        calcBaseRateItemMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteCalcBaseRateItem(Long id) {
        // 1. 校验存在
        validateCalcBaseRateItemExists(id);

        // 2. 删除
        calcBaseRateItemMapper.deleteById(id);
    }

    @Override
    public CalcBaseRateItemRespVO getCalcBaseRateItem(Long id) {
        CalcBaseRateItemDO item = calcBaseRateItemMapper.selectById(id);
        if (item == null) {
            return null;
        }
        return convertToRespVO(item);
    }

    @Override
    public List<CalcBaseRateItemRespVO> getCalcBaseRateItemList(Long calcBaseRateDirectoryId) {
        List<CalcBaseRateItemDO> items = calcBaseRateItemMapper.selectListByCalcBaseRateDirectoryId(calcBaseRateDirectoryId);
        return items.stream()
                .map(this::convertToRespVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<com.yhy.module.core.controller.admin.workbench.vo.calcbaserate.CalcBaseRateItemRespVO> getCalcBaseRateItemListForWorkbench(Long calcBaseRateDirectoryId) {
        List<CalcBaseRateItemDO> items = calcBaseRateItemMapper.selectListByCalcBaseRateDirectoryId(calcBaseRateDirectoryId);
        return items.stream()
                .map(this::convertToWorkbenchRespVO)
                .collect(Collectors.toList());
    }

    private com.yhy.module.core.controller.admin.workbench.vo.calcbaserate.CalcBaseRateItemRespVO convertToWorkbenchRespVO(CalcBaseRateItemDO item) {
        com.yhy.module.core.controller.admin.workbench.vo.calcbaserate.CalcBaseRateItemRespVO vo = new com.yhy.module.core.controller.admin.workbench.vo.calcbaserate.CalcBaseRateItemRespVO();
        vo.setId(item.getId());
        vo.setName(item.getName());
        vo.setRate(item.getRate());
        vo.setRemark(item.getRemark());
        vo.setSortOrder(item.getSortOrder());
        return vo;
    }

    // ==================== 私有方法 ====================

    private CalcBaseRateItemDO validateCalcBaseRateItemExists(Long id) {
        CalcBaseRateItemDO item = calcBaseRateItemMapper.selectById(id);
        if (item == null) {
            throw exception(CALC_BASE_RATE_ITEM_NOT_EXISTS);
        }
        return item;
    }

    private CalcBaseRateItemDO buildCalcBaseRateItemDO(CalcBaseRateItemSaveReqVO reqVO) {
        return CalcBaseRateItemDO.builder()
                .id(reqVO.getId())
                .calcBaseRateDirectoryId(reqVO.getCalcBaseRateDirectoryId())
                .name(reqVO.getName())
                .rate(reqVO.getRate())
                .remark(reqVO.getRemark())
                .sortOrder(reqVO.getSortOrder())
                .attributes(reqVO.getAttributes())
                .build();
    }

    private Integer getNextSortOrder(Long calcBaseRateDirectoryId) {
        List<CalcBaseRateItemDO> items = calcBaseRateItemMapper.selectListByCalcBaseRateDirectoryId(calcBaseRateDirectoryId);
        if (CollUtil.isEmpty(items)) {
            return 1;
        }
        return items.stream()
                .mapToInt(CalcBaseRateItemDO::getSortOrder)
                .max()
                .orElse(0) + 1;
    }

    private CalcBaseRateItemRespVO convertToRespVO(CalcBaseRateItemDO item) {
        CalcBaseRateItemRespVO vo = new CalcBaseRateItemRespVO();
        vo.setId(item.getId());
        vo.setCalcBaseRateDirectoryId(item.getCalcBaseRateDirectoryId());
        vo.setName(item.getName());
        vo.setRate(item.getRate());
        vo.setRemark(item.getRemark());
        vo.setSortOrder(item.getSortOrder());
        vo.setAttributes(item.getAttributes());
        vo.setCreateTime(item.getCreateTime());
        vo.setUpdateTime(item.getUpdateTime());
        return vo;
    }
}
