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.QuotaUnifiedFeeResourceSaveReqVO;
import com.yhy.module.core.dal.dataobject.quota.QuotaUnifiedFeeResourceDO;
import com.yhy.module.core.dal.mysql.quota.QuotaUnifiedFeeResourceMapper;
import com.yhy.module.core.enums.ErrorCodeConstants;
import com.yhy.module.core.service.quota.QuotaUnifiedFeeResourceService;
import java.util.List;
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 QuotaUnifiedFeeResourceServiceImpl implements QuotaUnifiedFeeResourceService {

    @Resource
    private QuotaUnifiedFeeResourceMapper unifiedFeeResourceMapper;

    @Resource
    private com.yhy.module.core.dal.mysql.quota.QuotaCatalogItemMapper quotaCatalogItemMapper;

    @Resource
    private com.yhy.module.core.dal.mysql.resource.ResourceItemMapper resourceItemMapper;

    @Resource
    private com.yhy.module.core.dal.mysql.resource.ResourceCatalogItemMapper resourceCatalogItemMapper;

    @Resource
    private com.yhy.module.core.dal.mysql.quota.QuotaUnifiedFeeSettingMapper unifiedFeeSettingMapper;

    @Resource
    private com.yhy.module.core.dal.mysql.resource.ResourceMergedMapper resourceMergedMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createUnifiedFeeResource(QuotaUnifiedFeeResourceSaveReqVO createReqVO) {
        // 1. 验证工料机是否在范围内
        validateResourceInScope(createReqVO.getUnifiedFeeSettingId(), createReqVO.getResourceItemId());
        
        // 2. 验证工料机是否存在
        com.yhy.module.core.dal.dataobject.resource.ResourceItemDO resourceItem = 
            resourceItemMapper.selectById(createReqVO.getResourceItemId());
        if (resourceItem == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.RESOURCE_ITEM_NOT_EXISTS);
        }
        
        // 3. 设置排序值
        if (createReqVO.getSortOrder() == null) {
            Integer maxSortOrder = unifiedFeeResourceMapper.selectMaxSortOrder(createReqVO.getUnifiedFeeSettingId());
            createReqVO.setSortOrder(maxSortOrder + 1);
        }

        // 4. 转换并插入
        QuotaUnifiedFeeResourceDO unifiedFeeResource = BeanUtil.copyProperties(createReqVO, QuotaUnifiedFeeResourceDO.class);
        unifiedFeeResourceMapper.insert(unifiedFeeResource);
        
        log.info("[createUnifiedFeeResource] 添加统一取费子目工料机成功，unifiedFeeSettingId={}, resourceItemId={}", 
            createReqVO.getUnifiedFeeSettingId(), createReqVO.getResourceItemId());
        
        return unifiedFeeResource.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUnifiedFeeResource(QuotaUnifiedFeeResourceSaveReqVO updateReqVO) {
        // 校验存在
        validateUnifiedFeeResourceExists(updateReqVO.getId());

        // 更新
        QuotaUnifiedFeeResourceDO updateObj = BeanUtil.copyProperties(updateReqVO, QuotaUnifiedFeeResourceDO.class);
        unifiedFeeResourceMapper.updateById(updateObj);
    }

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

        // 删除
        unifiedFeeResourceMapper.deleteById(id);
    }

    @Override
    public QuotaUnifiedFeeResourceDO getUnifiedFeeResource(Long id) {
        return unifiedFeeResourceMapper.selectById(id);
    }

    @Override
    public List<com.yhy.module.core.controller.admin.quota.vo.QuotaUnifiedFeeResourceRespVO> getUnifiedFeeResourceList(Long unifiedFeeSettingId) {
        List<QuotaUnifiedFeeResourceDO> list = unifiedFeeResourceMapper.selectListByUnifiedFeeSettingId(unifiedFeeSettingId);
        return list.stream().map(this::convertToVO).collect(java.util.stream.Collectors.toList());
    }
    
    /**
     * 转换DO为VO，并关联查询工料机详细信息
     */
    private com.yhy.module.core.controller.admin.quota.vo.QuotaUnifiedFeeResourceRespVO convertToVO(QuotaUnifiedFeeResourceDO resource) {
        com.yhy.module.core.controller.admin.quota.vo.QuotaUnifiedFeeResourceRespVO vo = 
            new com.yhy.module.core.controller.admin.quota.vo.QuotaUnifiedFeeResourceRespVO();
        BeanUtil.copyProperties(resource, vo);
        
        // 实时查询工料机信息（参考QuotaResourceServiceImpl.convertToVO，字段命名保持一致）
        com.yhy.module.core.dal.dataobject.resource.ResourceItemDO resourceItem = 
            resourceItemMapper.selectById(resource.getResourceItemId());
        if (resourceItem != null) {
            vo.setResourceCode(resourceItem.getCode());
            vo.setResourceName(resourceItem.getName());
            vo.setResourceSpec(resourceItem.getSpec());
            vo.setResourceUnit(resourceItem.getUnit());
            vo.setResourceType(resourceItem.getType());
            vo.setCalcBase(resourceItem.getCalcBase());
            
            // 判断是否为复合工料机
            boolean isMerged = resourceItem.getIsMerged() != null && resourceItem.getIsMerged() == 1;
            vo.setIsMerged(isMerged);
            
            if (isMerged) {
                // 复合工料机：税率和四个价格字段应该为空
                vo.setResourceTaxRate(null);
                vo.setResourceTaxExclBasePrice(null);
                vo.setResourceTaxInclBasePrice(null);
                vo.setResourceTaxExclCompilePrice(null);
                vo.setResourceTaxInclCompilePrice(null);
                
                // 查询复合工料机的子数据
                java.util.List<com.yhy.module.core.dal.dataobject.resource.ResourceMergedDO> mergedList = 
                    resourceMergedMapper.selectByMergedId(resourceItem.getId());
                if (mergedList != null && !mergedList.isEmpty()) {
                    java.util.List<com.yhy.module.core.controller.admin.quota.vo.QuotaUnifiedFeeResourceRespVO.MergedResourceItemVO> mergedItems = 
                        new java.util.ArrayList<>();
                    
                    java.math.BigDecimal totalTaxExclBase = java.math.BigDecimal.ZERO;
                    java.math.BigDecimal totalTaxInclBase = java.math.BigDecimal.ZERO;
                    java.math.BigDecimal totalTaxExclCompile = java.math.BigDecimal.ZERO;
                    java.math.BigDecimal totalTaxInclCompile = java.math.BigDecimal.ZERO;
                    
                    for (com.yhy.module.core.dal.dataobject.resource.ResourceMergedDO merged : mergedList) {
                        com.yhy.module.core.controller.admin.quota.vo.QuotaUnifiedFeeResourceRespVO.MergedResourceItemVO item = 
                            new com.yhy.module.core.controller.admin.quota.vo.QuotaUnifiedFeeResourceRespVO.MergedResourceItemVO();
                        item.setId(merged.getId());
                        item.setResourceItemId(merged.getSourceId());
                        item.setDosage(merged.getQuotaConsumption());
                        
                        // 查询子工料机详情
                        com.yhy.module.core.dal.dataobject.resource.ResourceItemDO childResource = 
                            resourceItemMapper.selectById(merged.getSourceId());
                        if (childResource != null) {
                            item.setResourceCode(childResource.getCode());
                            item.setResourceName(childResource.getName());
                            item.setResourceUnit(childResource.getUnit());
                            item.setResourceSpec(childResource.getSpec());
                            item.setResourceType(childResource.getType());
                            item.setResourceTaxRate(childResource.getTaxRate());
                            item.setResourceTaxExclBasePrice(childResource.getTaxExclBasePrice());
                            item.setResourceTaxInclBasePrice(childResource.getTaxInclBasePrice());
                            item.setResourceTaxExclCompilePrice(childResource.getTaxExclCompilePrice());
                            item.setResourceTaxInclCompilePrice(childResource.getTaxInclCompilePrice());
                            item.setCalcBase(childResource.getCalcBase());
                            
                            // 计算子项合价
                            java.math.BigDecimal childDosage = merged.getQuotaConsumption() != null ? merged.getQuotaConsumption() : java.math.BigDecimal.ZERO;
                            if (childResource.getTaxExclBasePrice() != null) {
                                java.math.BigDecimal sum = childResource.getTaxExclBasePrice().multiply(childDosage);
                                item.setTaxExclBaseTotalSum(sum);
                                totalTaxExclBase = totalTaxExclBase.add(sum);
                            }
                            if (childResource.getTaxInclBasePrice() != null) {
                                java.math.BigDecimal sum = childResource.getTaxInclBasePrice().multiply(childDosage);
                                item.setTaxInclBaseTotalSum(sum);
                                totalTaxInclBase = totalTaxInclBase.add(sum);
                            }
                            if (childResource.getTaxExclCompilePrice() != null) {
                                java.math.BigDecimal sum = childResource.getTaxExclCompilePrice().multiply(childDosage);
                                item.setTaxExclCompileTotalSum(sum);
                                totalTaxExclCompile = totalTaxExclCompile.add(sum);
                            }
                            if (childResource.getTaxInclCompilePrice() != null) {
                                java.math.BigDecimal sum = childResource.getTaxInclCompilePrice().multiply(childDosage);
                                item.setTaxInclCompileTotalSum(sum);
                                totalTaxInclCompile = totalTaxInclCompile.add(sum);
                            }
                        }
                        mergedItems.add(item);
                    }
                    vo.setMergedItems(mergedItems);
                    
                    // 复合工料机的合价 = 子项合价之和 × 父消耗量
                    java.math.BigDecimal parentQuantity = resource.getAdjustedDosage() != null ? 
                        resource.getAdjustedDosage() : (resource.getDosage() != null ? resource.getDosage() : java.math.BigDecimal.ONE);
                    vo.setTaxExclBaseTotalSum(totalTaxExclBase.multiply(parentQuantity));
                    vo.setTaxInclBaseTotalSum(totalTaxInclBase.multiply(parentQuantity));
                    vo.setTaxExclCompileTotalSum(totalTaxExclCompile.multiply(parentQuantity));
                    vo.setTaxInclCompileTotalSum(totalTaxInclCompile.multiply(parentQuantity));
                }
            } else {
                // 普通工料机
                vo.setResourceTaxRate(resourceItem.getTaxRate());
                vo.setResourceTaxExclBasePrice(resourceItem.getTaxExclBasePrice());
                vo.setResourceTaxInclBasePrice(resourceItem.getTaxInclBasePrice());
                vo.setResourceTaxExclCompilePrice(resourceItem.getTaxExclCompilePrice());
                vo.setResourceTaxInclCompilePrice(resourceItem.getTaxInclCompilePrice());
                
                // 计算合价 = 单价 × 消耗量（优先使用调整消耗量，否则使用定额消耗量）
                java.math.BigDecimal quantity = resource.getAdjustedDosage() != null ? 
                    resource.getAdjustedDosage() : resource.getDosage();
                if (quantity != null) {
                    if (resourceItem.getTaxExclBasePrice() != null) {
                        vo.setTaxExclBaseTotalSum(resourceItem.getTaxExclBasePrice().multiply(quantity));
                    }
                    if (resourceItem.getTaxInclBasePrice() != null) {
                        vo.setTaxInclBaseTotalSum(resourceItem.getTaxInclBasePrice().multiply(quantity));
                    }
                    if (resourceItem.getTaxExclCompilePrice() != null) {
                        vo.setTaxExclCompileTotalSum(resourceItem.getTaxExclCompilePrice().multiply(quantity));
                    }
                    if (resourceItem.getTaxInclCompilePrice() != null) {
                        vo.setTaxInclCompileTotalSum(resourceItem.getTaxInclCompilePrice().multiply(quantity));
                    }
                }
            }
        }
        
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchCreateUnifiedFeeResource(List<QuotaUnifiedFeeResourceSaveReqVO> createReqVOList) {
        for (QuotaUnifiedFeeResourceSaveReqVO createReqVO : createReqVOList) {
            createUnifiedFeeResource(createReqVO);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByUnifiedFeeSettingId(Long unifiedFeeSettingId) {
        unifiedFeeResourceMapper.deleteByUnifiedFeeSettingId(unifiedFeeSettingId);
    }

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

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

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

    @Override
    public void validateUnifiedFeeResourceExists(Long id) {
        if (unifiedFeeResourceMapper.selectById(id) == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.UNIFIED_FEE_RESOURCE_NOT_EXISTS);
        }
    }

    private QuotaUnifiedFeeResourceDO validateUnifiedFeeResourceExistsAndGet(Long id) {
        QuotaUnifiedFeeResourceDO unifiedFeeResource = unifiedFeeResourceMapper.selectById(id);
        if (unifiedFeeResource == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.UNIFIED_FEE_RESOURCE_NOT_EXISTS);
        }
        return unifiedFeeResource;
    }

    @Override
    public com.yhy.module.core.controller.admin.resource.vo.ResourceItemRespVO getResourceItemByCode(Long unifiedFeeSettingId, String code) {
        // 1. 获取统一取费设置绑定的工料机专业ID
        Long categoryTreeId = getCategoryTreeIdByUnifiedFeeSetting(unifiedFeeSettingId);
        
        // 2. 根据编码精确查询工料机
        com.yhy.module.core.dal.dataobject.resource.ResourceItemDO resourceItem = 
            resourceItemMapper.selectByCategoryTreeIdAndCode(categoryTreeId, code);
        
        // 3. 如果未找到返回null
        if (resourceItem == null) {
            return null;
        }
        
        // 4. 转换为 VO
        return convertResourceItemToVO(resourceItem);
    }

    @Override
    public void validateResourceInScope(Long unifiedFeeSettingId, Long resourceItemId) {
        // 1. 获取统一取费设置绑定的工料机专业ID
        Long allowedCategoryTreeId = getCategoryTreeIdByUnifiedFeeSetting(unifiedFeeSettingId);
        
        // 2. 获取工料机数据
        com.yhy.module.core.dal.dataobject.resource.ResourceItemDO resourceItem = resourceItemMapper.selectById(resourceItemId);
        if (resourceItem == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.RESOURCE_ITEM_NOT_EXISTS);
        }
        
        // 3. 获取工料机所属的目录节点（yhy_resource_catalog_item 表）
        com.yhy.module.core.dal.dataobject.resource.ResourceCatalogItemDO catalogItem = 
            resourceCatalogItemMapper.selectById(resourceItem.getCatalogItemId());
        if (catalogItem == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.RESOURCE_CATALOG_ITEM_NOT_EXISTS);
        }
        
        // 4. 验证工料机是否在范围内
        if (!allowedCategoryTreeId.equals(catalogItem.getCategoryTreeId())) {
            log.warn("[validateResourceInScope] 工料机不在统一取费设置的数据范围内，" +
                "unifiedFeeSettingId={}, resourceItemId={}, allowedCategoryTreeId={}, actualCategoryTreeId={}", 
                unifiedFeeSettingId, resourceItemId, allowedCategoryTreeId, catalogItem.getCategoryTreeId());
            
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.QUOTA_RESOURCE_OUT_OF_SCOPE);
        }
        
        log.debug("[validateResourceInScope] 工料机在范围内，unifiedFeeSettingId={}, resourceItemId={}", 
            unifiedFeeSettingId, resourceItemId);
    }

    @Override
    public java.util.List<com.yhy.module.core.controller.admin.resource.vo.ResourceItemRespVO> getAvailableResourceItemsWithFilter(
            Long unifiedFeeSettingId, String code, String name, String spec) {
        // 1. 获取统一取费设置绑定的工料机专业ID
        Long categoryTreeId = getCategoryTreeIdByUnifiedFeeSetting(unifiedFeeSettingId);
        
        // 2. 查询该专业下的所有工料机（支持模糊查询）
        java.util.List<com.yhy.module.core.dal.dataobject.resource.ResourceItemDO> resourceItems = 
            resourceItemMapper.selectByCategoryTreeIdWithFilter(categoryTreeId, code, name, spec);
        
        // 3. 转换为 VO
        return resourceItems.stream()
            .map(this::convertResourceItemToVO)
            .collect(java.util.stream.Collectors.toList());
    }

    /**
     * 获取统一取费设置绑定的工料机专业ID
     * 
     * 逻辑：统一取费设置 → catalog_item_id（费率模式节点） → 向上查找定额专业节点 → category_tree_id
     * 
     * 注意：费率模式节点(rate_mode)本身可能没有绑定工料机专业，需要向上查找父节点(specialty)的绑定
     */
    private Long getCategoryTreeIdByUnifiedFeeSetting(Long unifiedFeeSettingId) {
        // 1. 获取统一取费设置
        com.yhy.module.core.dal.dataobject.quota.QuotaUnifiedFeeSettingDO unifiedFeeSetting = 
            unifiedFeeSettingMapper.selectById(unifiedFeeSettingId);
        if (unifiedFeeSetting == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.UNIFIED_FEE_SETTING_NOT_EXISTS);
        }
        
        // 2. 获取费率模式节点（catalog_item_id 指向 yhy_quota_catalog_item）
        com.yhy.module.core.dal.dataobject.quota.QuotaCatalogItemDO catalogItem = 
            quotaCatalogItemMapper.selectById(unifiedFeeSetting.getCatalogItemId());
        if (catalogItem == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.QUOTA_CATALOG_ITEM_NOT_EXISTS);
        }
        
        // 3. 如果当前节点有绑定，直接返回
        if (catalogItem.getCategoryTreeId() != null) {
            return catalogItem.getCategoryTreeId();
        }
        
        // 4. 如果当前节点没有绑定，向上查找父节点的绑定（最多查找10层防止死循环）
        com.yhy.module.core.dal.dataobject.quota.QuotaCatalogItemDO currentNode = catalogItem;
        for (int i = 0; i < 10 && currentNode.getParentId() != null; i++) {
            com.yhy.module.core.dal.dataobject.quota.QuotaCatalogItemDO parentNode = 
                quotaCatalogItemMapper.selectById(currentNode.getParentId());
            if (parentNode == null) {
                break;
            }
            if (parentNode.getCategoryTreeId() != null) {
                log.debug("[getCategoryTreeIdByUnifiedFeeSetting] 从父节点获取categoryTreeId, " +
                    "unifiedFeeSettingId={}, parentNodeId={}, categoryTreeId={}", 
                    unifiedFeeSettingId, parentNode.getId(), parentNode.getCategoryTreeId());
                return parentNode.getCategoryTreeId();
            }
            currentNode = parentNode;
        }
        
        // 5. 如果向上查找也没有找到，抛出异常
        throw ServiceExceptionUtil.exception(ErrorCodeConstants.QUOTA_SPECIALTY_NOT_BOUND);
    }

    /**
     * 转换 ResourceItemDO 为 ResourceItemRespVO
     */
    private com.yhy.module.core.controller.admin.resource.vo.ResourceItemRespVO convertResourceItemToVO(
            com.yhy.module.core.dal.dataobject.resource.ResourceItemDO resourceItem) {
        com.yhy.module.core.controller.admin.resource.vo.ResourceItemRespVO vo = 
            new com.yhy.module.core.controller.admin.resource.vo.ResourceItemRespVO();
        BeanUtil.copyProperties(resourceItem, vo);
        return vo;
    }
}
