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

import cn.hutool.core.bean.BeanUtil;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import com.yhy.module.core.controller.admin.quota.vo.QuotaFeeItemWithRateRespVO;
import com.yhy.module.core.controller.admin.quota.vo.QuotaUnifiedFeeSaveReqVO;
import com.yhy.module.core.dal.dataobject.quota.QuotaFeeItemDO;
import com.yhy.module.core.dal.dataobject.quota.QuotaUnifiedFeeDO;
import com.yhy.module.core.dal.mysql.quota.QuotaFeeItemMapper;
import com.yhy.module.core.dal.mysql.quota.QuotaUnifiedFeeMapper;
import com.yhy.module.core.enums.ErrorCodeConstants;
import com.yhy.module.core.service.quota.QuotaFeeItemService;
import com.yhy.module.core.service.quota.QuotaUnifiedFeeService;
import java.util.List;
import java.util.Map;
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 实现类
 */
@Service
@Validated
@Slf4j
public class QuotaUnifiedFeeServiceImpl implements QuotaUnifiedFeeService {

    @Resource
    private QuotaUnifiedFeeMapper unifiedFeeMapper;

    @Resource
    private QuotaFeeItemMapper feeItemMapper;

    @Resource
    private QuotaFeeItemService quotaFeeItemService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createUnifiedFee(QuotaUnifiedFeeSaveReqVO createReqVO) {
        // 设置默认节点类型
        if (createReqVO.getNodeType() == null) {
            createReqVO.setNodeType(createReqVO.getParentId() == null ? 
                QuotaUnifiedFeeDO.NODE_TYPE_PARENT : QuotaUnifiedFeeDO.NODE_TYPE_CHILD);
        }

        // 设置排序值
        if (createReqVO.getSortOrder() == null) {
            Integer maxSortOrder = unifiedFeeMapper.selectMaxSortOrder(
                createReqVO.getCatalogItemId(), createReqVO.getParentId());
            createReqVO.setSortOrder(maxSortOrder + 1);
        }

        // 转换并插入
        QuotaUnifiedFeeDO unifiedFee = BeanUtil.copyProperties(createReqVO, QuotaUnifiedFeeDO.class);
        unifiedFeeMapper.insert(unifiedFee);
        return unifiedFee.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUnifiedFee(QuotaUnifiedFeeSaveReqVO updateReqVO) {
        // 验证计算基数格式和公式语法
        if (updateReqVO.getCalcBase() != null) {
            quotaFeeItemService.validateCalcBase(updateReqVO.getCalcBase());
        }

        QuotaUnifiedFeeDO updateObj;
        
        // 如果id为空但feeItemId不为空，通过feeItemId查找
        if (updateReqVO.getId() == null && updateReqVO.getFeeItemId() != null && updateReqVO.getCatalogItemId() != null) {
            // 通过feeItemId和catalogItemId查找
            QuotaUnifiedFeeDO existing = unifiedFeeMapper.selectByFeeItemIdAndCatalogItemId(
                updateReqVO.getFeeItemId(), updateReqVO.getCatalogItemId());
            
            if (existing != null) {
                // 存在则更新
                updateObj = BeanUtil.copyProperties(updateReqVO, QuotaUnifiedFeeDO.class);
                updateObj.setId(existing.getId());
            } else {
                // 不存在则创建
                updateObj = new QuotaUnifiedFeeDO();
                updateObj.setCatalogItemId(updateReqVO.getCatalogItemId());
                updateObj.setFeeItemId(updateReqVO.getFeeItemId());
                updateObj.setCalcBase(updateReqVO.getCalcBase());
                updateObj.setSortOrder(0);
                unifiedFeeMapper.insert(updateObj);
                return;
            }
        } else {
            // 校验存在
            validateUnifiedFeeExists(updateReqVO.getId());
            updateObj = BeanUtil.copyProperties(updateReqVO, QuotaUnifiedFeeDO.class);
        }

        // 更新
        unifiedFeeMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteUnifiedFee(Long id) {
        // 校验存在
        QuotaUnifiedFeeDO unifiedFee = validateUnifiedFeeExistsAndGet(id);

        // 如果有子节点，需要先删除子节点
        if (unifiedFeeMapper.hasChildren(id)) {
            List<QuotaUnifiedFeeDO> children = unifiedFeeMapper.selectChildListByParentId(id);
            for (QuotaUnifiedFeeDO child : children) {
                unifiedFeeMapper.deleteById(child.getId());
            }
        }

        // 删除本节点
        unifiedFeeMapper.deleteById(id);
    }

    @Override
    public QuotaUnifiedFeeDO getUnifiedFee(Long id) {
        return unifiedFeeMapper.selectById(id);
    }

    @Override
    public List<QuotaUnifiedFeeDO> getUnifiedFeeList(Long catalogItemId) {
        return unifiedFeeMapper.selectListByCatalogItemId(catalogItemId);
    }

    @Override
    public List<QuotaFeeItemWithRateRespVO> getUnifiedFeeTree(Long catalogItemId) {
        // 1. 获取定额取费的费率项+取费项合并视图（与定额取费页面显示一致）
        List<QuotaFeeItemWithRateRespVO> feeItemWithRateList = quotaFeeItemService.getFeeItemWithRateList(catalogItemId);
        
        // 2. 获取统一取费单价的calcBase覆盖值
        List<QuotaUnifiedFeeDO> unifiedFees = unifiedFeeMapper.selectListByCatalogItemId(catalogItemId);
        Map<Long, QuotaUnifiedFeeDO> unifiedFeeByFeeItemIdMap = unifiedFees.stream()
            .filter(item -> item.getFeeItemId() != null)
            .collect(Collectors.toMap(QuotaUnifiedFeeDO::getFeeItemId, item -> item, (a, b) -> a));
        
        // 3. 合并calcBase覆盖值（如果统一取费单价有覆盖，则使用覆盖值）
        mergeCalcBaseOverrides(feeItemWithRateList, unifiedFeeByFeeItemIdMap);
        
        return feeItemWithRateList;
    }
    
    /**
     * 递归合并calcBase覆盖值
     */
    private void mergeCalcBaseOverrides(List<QuotaFeeItemWithRateRespVO> items, Map<Long, QuotaUnifiedFeeDO> unifiedFeeMap) {
        if (items == null) return;
        for (QuotaFeeItemWithRateRespVO item : items) {
            if (item.getFeeItemId() != null) {
                QuotaUnifiedFeeDO unifiedFee = unifiedFeeMap.get(item.getFeeItemId());
                if (unifiedFee != null && unifiedFee.getCalcBase() != null) {
                    // 使用统一取费单价的覆盖值
                    item.setCalcBase(unifiedFee.getCalcBase());
                }
            }
            // 递归处理子节点
            mergeCalcBaseOverrides(item.getChildren(), unifiedFeeMap);
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void initFromFeeItems(Long catalogItemId) {
        // 获取定额取费项
        List<QuotaFeeItemDO> feeItems = feeItemMapper.selectListByCatalogItemId(catalogItemId);
        if (feeItems.isEmpty()) {
            return;
        }
        
        // 获取已存在的统一取费单价（按fee_item_id）
        List<QuotaUnifiedFeeDO> existingItems = unifiedFeeMapper.selectListByCatalogItemId(catalogItemId);
        java.util.Set<Long> existingFeeItemIds = existingItems.stream()
            .filter(item -> item.getFeeItemId() != null)
            .map(QuotaUnifiedFeeDO::getFeeItemId)
            .collect(Collectors.toSet());
        
        // 为每个定额取费项创建对应的统一取费单价（如果不存在）
        int sortOrder = existingItems.size();
        for (QuotaFeeItemDO feeItem : feeItems) {
            if (!existingFeeItemIds.contains(feeItem.getId())) {
                QuotaUnifiedFeeDO unifiedFee = new QuotaUnifiedFeeDO();
                unifiedFee.setCatalogItemId(catalogItemId);
                unifiedFee.setFeeItemId(feeItem.getId());
                // 不复制其他字段，从定额取费动态获取
                unifiedFee.setSortOrder(++sortOrder);
                unifiedFeeMapper.insert(unifiedFee);
                log.debug("[initFromFeeItems] 创建统一取费单价, catalogItemId={}, feeItemId={}", 
                    catalogItemId, feeItem.getId());
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void swapSort(Long nodeId1, Long nodeId2) {
        QuotaUnifiedFeeDO node1 = validateUnifiedFeeExistsAndGet(nodeId1);
        QuotaUnifiedFeeDO node2 = validateUnifiedFeeExistsAndGet(nodeId2);

        // 交换排序值
        Integer tempSort = node1.getSortOrder();
        node1.setSortOrder(node2.getSortOrder());
        node2.setSortOrder(tempSort);

        unifiedFeeMapper.updateById(node1);
        unifiedFeeMapper.updateById(node2);
    }

    @Override
    public void validateUnifiedFeeExists(Long id) {
        if (unifiedFeeMapper.selectById(id) == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.UNIFIED_FEE_NOT_EXISTS);
        }
    }

    private QuotaUnifiedFeeDO validateUnifiedFeeExistsAndGet(Long id) {
        QuotaUnifiedFeeDO unifiedFee = unifiedFeeMapper.selectById(id);
        if (unifiedFee == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.UNIFIED_FEE_NOT_EXISTS);
        }
        return unifiedFee;
    }
}
