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

import cn.hutool.core.bean.BeanUtil;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import com.yhy.module.core.controller.admin.workbench.vo.WbBoqMarketMaterialRespVO;
import com.yhy.module.core.controller.admin.workbench.vo.WbBoqMarketMaterialSaveReqVO;
import com.yhy.module.core.dal.dataobject.quota.QuotaMarketMaterialDO;
import com.yhy.module.core.dal.dataobject.resource.ResourceItemDO;
import com.yhy.module.core.dal.dataobject.workbench.WbAdjustmentSettingDO;
import com.yhy.module.core.dal.dataobject.workbench.WbBoqMarketMaterialDO;
import com.yhy.module.core.dal.mysql.quota.QuotaMarketMaterialMapper;
import com.yhy.module.core.dal.mysql.resource.ResourceItemMapper;
import com.yhy.module.core.dal.mysql.workbench.WbAdjustmentSettingMapper;
import com.yhy.module.core.dal.mysql.workbench.WbBoqMarketMaterialMapper;
import com.yhy.module.core.enums.ErrorCodeConstants;
import com.yhy.module.core.service.workbench.WbBoqMarketMaterialService;
import com.yhy.module.core.util.AdjustmentFormulaCalculator;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
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 WbBoqMarketMaterialServiceImpl implements WbBoqMarketMaterialService {

    @Resource
    private WbBoqMarketMaterialMapper wbBoqMarketMaterialMapper;

    @Resource
    private QuotaMarketMaterialMapper quotaMarketMaterialMapper;

    @Resource
    private ResourceItemMapper resourceItemMapper;

    @Resource
    private WbAdjustmentSettingMapper wbAdjustmentSettingMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createMarketMaterial(WbBoqMarketMaterialSaveReqVO createReqVO) {
        WbBoqMarketMaterialDO marketMaterial = BeanUtil.copyProperties(createReqVO, WbBoqMarketMaterialDO.class);
        marketMaterial.setTenantId(TenantContextHolder.getTenantId());
        
        // 处理 sortOrder
        if (marketMaterial.getSortOrder() == null) {
            Integer maxSortOrder = getMaxSortOrder(createReqVO.getDivisionId());
            marketMaterial.setSortOrder(maxSortOrder + 1);
        }
        
        wbBoqMarketMaterialMapper.insert(marketMaterial);
        return marketMaterial.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateMarketMaterial(WbBoqMarketMaterialSaveReqVO updateReqVO) {
        validateExists(updateReqVO.getId());
        
        WbBoqMarketMaterialDO updateObj = BeanUtil.copyProperties(updateReqVO, WbBoqMarketMaterialDO.class);
        wbBoqMarketMaterialMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteMarketMaterial(Long id) {
        validateExists(id);
        wbBoqMarketMaterialMapper.deleteById(id);
    }

    @Override
    public WbBoqMarketMaterialDO getMarketMaterial(Long id) {
        return wbBoqMarketMaterialMapper.selectById(id);
    }

    @Override
    public List<WbBoqMarketMaterialRespVO> getMarketMaterialList(Long divisionId) {
        List<WbBoqMarketMaterialDO> list = wbBoqMarketMaterialMapper.selectListByDivisionId(divisionId);
        List<WbBoqMarketMaterialRespVO> result = list.stream().map(this::convertToVO).collect(Collectors.toList());
        
        // 计算调整公式（虚拟字段），与子目工料机逻辑一致
        calculateAdjustmentFormulas(divisionId, result);
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void copyFromQuota(Long divisionId, Long quotaItemId) {
        // 1. 查询定额基价下的市场主材设备
        List<QuotaMarketMaterialDO> quotaMaterials = quotaMarketMaterialMapper.selectListByQuotaItemId(quotaItemId);
        if (quotaMaterials == null || quotaMaterials.isEmpty()) {
            return;
        }
        
        // 2. 复制到工作台
        List<WbBoqMarketMaterialDO> wbMaterials = new ArrayList<>();
        for (QuotaMarketMaterialDO quotaMaterial : quotaMaterials) {
            WbBoqMarketMaterialDO wbMaterial = convertFromQuota(quotaMaterial, divisionId);
            wbMaterials.add(wbMaterial);
        }
        
        // 3. 批量插入
        wbBoqMarketMaterialMapper.insertBatch(wbMaterials);
        
        log.info("[copyFromQuota] 复制市场主材设备成功，divisionId={}, quotaItemId={}, count={}", 
            divisionId, quotaItemId, wbMaterials.size());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByDivisionIds(List<Long> divisionIds) {
        if (divisionIds == null || divisionIds.isEmpty()) {
            return;
        }
        wbBoqMarketMaterialMapper.deleteByDivisionIds(divisionIds);
    }

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

    private WbBoqMarketMaterialDO validateExists(Long id) {
        WbBoqMarketMaterialDO marketMaterial = wbBoqMarketMaterialMapper.selectById(id);
        if (marketMaterial == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.WB_BOQ_MARKET_MATERIAL_NOT_EXISTS);
        }
        return marketMaterial;
    }

    private Integer getMaxSortOrder(Long divisionId) {
        List<WbBoqMarketMaterialDO> materials = wbBoqMarketMaterialMapper.selectListByDivisionId(divisionId);
        if (materials == null || materials.isEmpty()) {
            return 0;
        }
        return materials.stream()
                .map(WbBoqMarketMaterialDO::getSortOrder)
                .filter(java.util.Objects::nonNull)
                .max(Integer::compareTo)
                .orElse(0);
    }

    private WbBoqMarketMaterialDO convertFromQuota(QuotaMarketMaterialDO quotaMaterial, Long divisionId) {
        WbBoqMarketMaterialDO wbMaterial = new WbBoqMarketMaterialDO();
        wbMaterial.setTenantId(TenantContextHolder.getTenantId());
        wbMaterial.setDivisionId(divisionId);
        wbMaterial.setSourceResourceItemId(quotaMaterial.getResourceItemId());
        wbMaterial.setSourceMarketMaterialId(quotaMaterial.getId());
        wbMaterial.setConsumeQty(quotaMaterial.getDosage());
        wbMaterial.setAdjustConsumeQty(quotaMaterial.getAdjustedDosage());
        wbMaterial.setSortOrder(quotaMaterial.getSortOrder());
        wbMaterial.setSourceType(WbBoqMarketMaterialDO.SOURCE_TYPE_SYSTEM);
        wbMaterial.setAttributes(quotaMaterial.getAttributes());
        
        // 从工料机库获取信息
        ResourceItemDO resourceItem = resourceItemMapper.selectById(quotaMaterial.getResourceItemId());
        if (resourceItem != null) {
            wbMaterial.setCode(resourceItem.getCode());
            wbMaterial.setName(resourceItem.getName());
            wbMaterial.setSpec(resourceItem.getSpec());
            wbMaterial.setUnit(resourceItem.getUnit());
            wbMaterial.setResourceType(convertTypeToDisplay(resourceItem.getType()));
            wbMaterial.setCategoryId(resourceItem.getCategoryId());
            wbMaterial.setTaxRate(resourceItem.getTaxRate());
            wbMaterial.setTaxExclBasePrice(resourceItem.getTaxExclBasePrice());
            wbMaterial.setTaxInclBasePrice(resourceItem.getTaxInclBasePrice());
            wbMaterial.setTaxExclCompilePrice(resourceItem.getTaxExclCompilePrice());
            wbMaterial.setTaxInclCompilePrice(resourceItem.getTaxInclCompilePrice());
        }
        
        return wbMaterial;
    }

    private WbBoqMarketMaterialRespVO convertToVO(WbBoqMarketMaterialDO marketMaterial) {
        WbBoqMarketMaterialRespVO vo = BeanUtil.copyProperties(marketMaterial, WbBoqMarketMaterialRespVO.class);
        
        // 从源工料机获取 calcBase
        if (marketMaterial.getSourceResourceItemId() != null) {
            ResourceItemDO resourceItem = resourceItemMapper.selectById(marketMaterial.getSourceResourceItemId());
            if (resourceItem != null) {
                vo.setCalcBase(resourceItem.getCalcBase());
            }
        }
        
        // 计算合价
        BigDecimal effectiveQty = marketMaterial.getAdjustConsumeQty() != null 
            ? marketMaterial.getAdjustConsumeQty() 
            : marketMaterial.getConsumeQty();
        
        if (effectiveQty != null) {
            vo.setTaxExclBaseTotalSum(multiplyOrZero(marketMaterial.getTaxExclBasePrice(), effectiveQty));
            vo.setTaxInclBaseTotalSum(multiplyOrZero(marketMaterial.getTaxInclBasePrice(), effectiveQty));
            vo.setTaxExclCompileTotalSum(multiplyOrZero(marketMaterial.getTaxExclCompilePrice(), effectiveQty));
            vo.setTaxInclCompileTotalSum(multiplyOrZero(marketMaterial.getTaxInclCompilePrice(), effectiveQty));
        }
        
        // 格式化数值
        formatVO(vo);
        
        return vo;
    }

    private void formatVO(WbBoqMarketMaterialRespVO vo) {
        // 价格/税率/合价：2位小数
        vo.setTaxRate(roundToScale(vo.getTaxRate(), 2));
        vo.setTaxExclBasePrice(roundToScale(vo.getTaxExclBasePrice(), 2));
        vo.setTaxInclBasePrice(roundToScale(vo.getTaxInclBasePrice(), 2));
        vo.setTaxExclCompilePrice(roundToScale(vo.getTaxExclCompilePrice(), 2));
        vo.setTaxInclCompilePrice(roundToScale(vo.getTaxInclCompilePrice(), 2));
        vo.setTaxExclBaseTotalSum(roundToScale(vo.getTaxExclBaseTotalSum(), 2));
        vo.setTaxInclBaseTotalSum(roundToScale(vo.getTaxInclBaseTotalSum(), 2));
        vo.setTaxExclCompileTotalSum(roundToScale(vo.getTaxExclCompileTotalSum(), 2));
        vo.setTaxInclCompileTotalSum(roundToScale(vo.getTaxInclCompileTotalSum(), 2));
        
        // 消耗量：4位小数
        vo.setConsumeQty(roundToScale(vo.getConsumeQty(), 4));
        vo.setAdjustConsumeQty(roundToScale(vo.getAdjustConsumeQty(), 4));
    }

    private BigDecimal roundToScale(BigDecimal value, int scale) {
        if (value == null) {
            return null;
        }
        return value.setScale(scale, RoundingMode.HALF_UP);
    }

    private BigDecimal multiplyOrZero(BigDecimal a, BigDecimal b) {
        if (a == null || b == null) {
            return BigDecimal.ZERO;
        }
        return a.multiply(b);
    }

    private String convertTypeToDisplay(String type) {
        if (type == null) {
            return null;
        }
        switch (type) {
            case "1":
                return "labor";
            case "2":
                return "material";
            case "3":
                return "machine";
            default:
                return type;
        }
    }

    /**
     * 计算调整公式（虚拟字段）
     * 与子目工料机逻辑一致，使用公共工具类 AdjustmentFormulaCalculator
     */
    private void calculateAdjustmentFormulas(Long divisionId, List<WbBoqMarketMaterialRespVO> materials) {
        List<WbAdjustmentSettingDO> settings = wbAdjustmentSettingMapper.selectListByDivisionId(divisionId);
        if (settings == null || settings.isEmpty()) {
            return;
        }
        
        AdjustmentFormulaCalculator.calculateFormulas(
                materials,
                settings,
                WbBoqMarketMaterialRespVO::getCode,
                WbBoqMarketMaterialRespVO::getCategoryId,
                WbBoqMarketMaterialRespVO::setAdjustmentFormula
        );
    }
}
