package com.njzscloud.dispose.mfg.bom.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njzscloud.common.core.ex.Exceptions;
import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult;
import com.njzscloud.common.sn.support.SnUtil;
import com.njzscloud.dispose.mfg.bom.constant.MtlType;
import com.njzscloud.dispose.mfg.bom.mapper.BomMapper;
import com.njzscloud.dispose.mfg.bom.pojo.dto.BomAddDto;
import com.njzscloud.dispose.mfg.bom.pojo.dto.BomDetailAddDto;
import com.njzscloud.dispose.mfg.bom.pojo.dto.BomQueryDto;
import com.njzscloud.dispose.mfg.bom.pojo.entity.BomDetailEntity;
import com.njzscloud.dispose.mfg.bom.pojo.entity.BomEntity;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

/**
 * 物料清单
 *
 * @author ljw
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BomService extends ServiceImpl<BomMapper, BomEntity> implements IService<BomEntity> {

    private final BomDetailService bomDetailService;

    /**
     * 新增
     */
    @Transactional(rollbackFor = Exception.class)
    public void add(BomAddDto bomAddDTO) {
        BomEntity bomEntity = BeanUtil.copyProperties(bomAddDTO, BomEntity.class).setSn(this.generateSn());

        // 校验版本号唯一性
        validateBomVersionUniqueness(bomEntity.getGoodId(), bomEntity.getBomVer(), null);
        // 校验可用性（同一主产品ID只能有一个可用的BOM）
        validateBomAvailability(bomEntity.getGoodId(), null);

        // 预校验明细数据
        validateBomDetails(bomAddDTO.getDetails(), bomEntity.getGoodId());

        // 保存BOM主表
        this.save(bomEntity);

        // 保存BOM明细
        for (BomDetailAddDto detail : bomAddDTO.getDetails()) {
            // 直接保存，不使用BomDetailService的add方法（避免重复校验）
            BomDetailEntity detailEntity = BeanUtil.copyProperties(detail, BomDetailEntity.class).setBomId(bomEntity.getId());
            bomDetailService.save(detailEntity);
        }
    }

    /**
     * 修改
     */
    public void modify(BomEntity bomEntity) {
        this.updateById(bomEntity);
    }

    /**
     * 删除
     */
    @Transactional(rollbackFor = Exception.class)
    public void del(List<Long> ids) {
        this.removeBatchByIds(ids);
    }

    /**
     * 详情
     */
    public BomEntity detail(Long id) {
        return this.getById(id);
    }

    /**
     * 分页查询
     */
    public PageResult<BomEntity> paging(PageParam pageParam, BomQueryDto queryDto) {
        return PageResult.of(this.page(pageParam.toPage(), Wrappers.<BomEntity>lambdaQuery()
            .like(StrUtil.isNotBlank(queryDto.getSn()), BomEntity::getSn, queryDto.getSn())
            .eq(queryDto.getGoodId() != null, BomEntity::getGoodId, queryDto.getGoodId())
            .eq(queryDto.getCanuse() != null, BomEntity::getCanuse, queryDto.getCanuse())));
    }

    /**
     * 校验BOM版本号唯一性
     *
     * @param goodId    主产品ID
     * @param bomVer    版本号
     * @param excludeId 排除的ID（用于修改时排除自身）
     */
    private void validateBomVersionUniqueness(Long goodId, String bomVer, Long excludeId) {

        long count = this.count(Wrappers.<BomEntity>lambdaQuery()
            .eq(BomEntity::getGoodId, goodId)
            .eq(BomEntity::getBomVer, bomVer)
            .ne(excludeId != null, BomEntity::getId, excludeId));

        if (count > 0) {
            throw Exceptions.clierr("同一主产品的物料版本号必须唯一");
        }
    }

    /**
     * 校验BOM可用性（同一主产品ID只能有一个可用的BOM）
     *
     * @param goodId    主产品ID
     * @param excludeId 排除的ID（用于修改时排除自身）
     */
    private void validateBomAvailability(Long goodId, Long excludeId) {
        long count = this.count(Wrappers.<BomEntity>lambdaQuery()
            .eq(BomEntity::getGoodId, goodId)
            .eq(BomEntity::getCanuse, Boolean.TRUE)
            .ne(excludeId != null, BomEntity::getId, excludeId));

        if (count > 0) {
            throw Exceptions.clierr("同一主产品只能有一个可用的物料");
        }
    }


    /**
     * 预校验BOM明细数据
     *
     * @param details       明细列表
     * @param mainProductId 主产品ID
     */
    private void validateBomDetails(List<BomDetailAddDto> details, Long mainProductId) {
        if (details == null || details.isEmpty()) {
            throw Exceptions.clierr("必须包含至少一个明细");
        }

        boolean hasMainProduct = false;

        for (BomDetailAddDto detail : details) {
            // 校验产出物料数量必须为1
            if (Boolean.TRUE.equals(detail.getChu()) && (detail.getQuantity() == null || detail.getQuantity().compareTo(BigDecimal.ONE) != 0)) {
                throw Exceptions.clierr("产出物料的数量必须为1");
            }

            // 检查是否包含主产品明细
            if (detail.getGoodsId() != null && detail.getGoodsId().equals(mainProductId)) {
                if (detail.getMtlType() == MtlType.ZhuChanPin) {
                    hasMainProduct = true;
                } else {
                    throw Exceptions.clierr("与主产品ID相同的产品必须是主产品类型");
                }
            }
        }

        if (!hasMainProduct) {
            throw Exceptions.clierr("明细中必须包含与主产品ID相同且类型为主产品的记录");
        }
    }

    /**
     * 生成编码
     *
     * @return sn 编码
     */
    public String generateSn() {
        String sn = SnUtil.next("Bom-SN");
        if (this.exists(Wrappers.<BomEntity>lambdaQuery().eq(BomEntity::getSn, sn).eq(BomEntity::getDeleted, Boolean.FALSE))) {
            this.generateSn();
        }
        return sn;
    }
}
