package cn.iocoder.yudao.module.erp.service.mold;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.common.controller.admin.mold.vo.*;
import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldBrandDO;
import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldBrandProductDO;
import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO;
import cn.iocoder.yudao.module.common.dal.dataobject.moldrepair.MoldRepairDO;
import cn.iocoder.yudao.module.common.dal.dataobject.moldrepair.MoldRepairLineDO;
import cn.iocoder.yudao.module.common.dal.dataobject.moldticketresults.MoldTicketResultsDO;
import cn.iocoder.yudao.module.erp.controller.admin.mold.vo.MoldBrandTreeRespVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO;
import cn.iocoder.yudao.module.common.dal.mysql.mold.MoldBrandMapper;
import cn.iocoder.yudao.module.common.dal.mysql.mold.MoldBrandProductMapper;
import cn.iocoder.yudao.module.common.dal.mysql.mold.MoldMapper;
import cn.iocoder.yudao.module.common.dal.mysql.moldrepair.MoldRepairLineMapper;
import cn.iocoder.yudao.module.common.dal.mysql.moldrepair.MoldRepairMapper;
import cn.iocoder.yudao.module.common.dal.mysql.moldticketresults.MoldTicketResultsMapper;
import cn.iocoder.yudao.module.common.controller.admin.moldticketmanagement.enums.MoldPlanTypeEnum;
import cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
import cn.iocoder.yudao.module.erp.service.product.ErpProductUnitService;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;

/**
 * 模具型号 Service 实现类
 *
 * @author 内蒙必硕
 */
@Service
@Validated
public class MoldBrandServiceImpl implements MoldBrandService {

    @Resource
    private MoldBrandMapper moldBrandMapper;
    @Resource
    private MoldMapper moldMapper;
    @Resource
    private MoldRepairMapper moldRepairMapperRepair;
    @Resource
    private MoldRepairLineMapper moldRepairLineMapper;
    @Resource
    private MoldTicketResultsMapper moldticketResultsMapper;
    @Resource
    private ErpProductUnitService productUnitService;
    @Resource
    private ErpProductService productService;
    @Override
    public Long createMoldBrand(MoldBrandSaveReqVO createReqVO) {
        // 插入
//        MoldBrandDO moldBrand = BeanUtils.toBean(createReqVO, MoldBrandDO.class);
        String Code = createReqVO.getCode();
        if (StrUtil.isBlank(Code)) {
            throw new ServiceException(ErrorCodeConstants.MOLD_BRAND_CODE_EMPTY);
        }
        boolean exists = moldBrandMapper.exists(
                new LambdaQueryWrapperX<MoldBrandDO>().eq(MoldBrandDO::getCode, Code)
        );
        if (exists) {
            throw new ServiceException(ErrorCodeConstants.MOLD_BRAND_CODE_DUPLICATE);
        }
        MoldBrandDO moldBrand = BeanUtils.toBean(createReqVO, MoldBrandDO.class);
        moldBrandMapper.insert(moldBrand);
        // 返回
        return moldBrand.getId();
    }

    @Override
    public void updateMoldBrand(MoldBrandSaveReqVO updateReqVO) {
        // 校验存在
        validateMoldBrandExists(updateReqVO.getId());
        // 更新
        MoldBrandDO updateObj = BeanUtils.toBean(updateReqVO, MoldBrandDO.class);
        moldBrandMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteMoldBrand(Long id) {
        // 校验存在
        validateMoldBrandExists(id);
        // 删除
        moldBrandMapper.deleteById(id);

        // 删除子表
        deleteMoldByBrandId(id);
    }

    private void validateMoldBrandExists(Long id) {
        if (moldBrandMapper.selectById(id) == null) {
            throw exception(MOLD_BRAND_NOT_EXISTS);
        }
    }

    @Override
    public MoldBrandDO getMoldBrand(Long id) {
        return moldBrandMapper.selectById(id);
    }
    @Override
    public List<MoldBrandDO> selectBy(MoldBrandPageReqVO reqVO){
        return moldBrandMapper.selectBy(reqVO);
    }

    @Override
    public PageResult<MoldBrandRespVO> getMoldBrandPage(MoldBrandPageReqVO pageReqVO) {
        PageResult<MoldBrandDO> pageResult = moldBrandMapper.selectPage(pageReqVO);
        return new PageResult<>(buildMoldBrandVOList(pageResult.getList()), pageResult.getTotal());
    }

    private List<MoldBrandRespVO> buildMoldBrandVOList(List<MoldBrandDO> list) {
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        Map<Long, ErpProductDO> map = productService.getProductMap(
                convertSet(list, MoldBrandDO::getProductId));
        return BeanUtils.toBean(list, MoldBrandRespVO.class, item -> {
            MapUtils.findAndThen(map, item.getProductId(),
                    product -> item.setProductName(product.getName()));
        });
    }
    @Override
    public List<MoldBrandDO> getList(Collection<Long> ids) {
        return moldBrandMapper.selectBatchIds(ids);
    }
    // ==================== 子表（模具） ====================

    @Override
    public PageResult<MoldRespVO> getMoldPage(PageParam pageReqVO, Long brandId) {
        PageResult<MoldDO> pageResult = moldMapper.selectPage(pageReqVO, brandId);
        return new PageResult<>(buildMoldVOList(pageResult.getList()), pageResult.getTotal());
    }
    @Override
    public PageResult<MoldRespVO> getMoldPage(MoldPageReqVO pageReqVO) {
        PageResult<MoldDO> pageResult = moldMapper.selectPage(pageReqVO);
        return new PageResult<>(buildMoldVOList(pageResult.getList()), pageResult.getTotal());
    }

    @Override
    public List<MoldDO> getMoldList() {
        return moldMapper.selectList();
    }

    private List<MoldRespVO> buildMoldVOList(List<MoldDO> list) {
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        Map<Long, ErpProductUnitDO> unitMap = productUnitService.getProductUnitMap(
                convertSet(list, MoldDO::getUnitId));
        return BeanUtils.toBean(list, MoldRespVO.class, product -> {
            MapUtils.findAndThen(unitMap, product.getUnitId(),
                    unit -> product.setUnitName(unit.getName()));
        });
    }
    @Override
    public Long createMold(MoldSaveReqVO createReqVO) {
        String Code = createReqVO.getCode();
        if (StrUtil.isBlank(Code)) {
            throw new ServiceException(ErrorCodeConstants.MOLD_CODE_EMPTY);
        }
        boolean exists = moldMapper.exists(
                new LambdaQueryWrapperX<MoldDO>().eq(MoldDO::getCode, Code)
        );
        if (exists) {
            throw new ServiceException(ErrorCodeConstants.MOLD_CODE_DUPLICATE);
        }
        MoldDO mold = BeanUtils.toBean(createReqVO, MoldDO.class);
        moldMapper.insert(mold);
        return mold.getId();
    }

    @Override
    public void updateMold(MoldDO mold) {
        // 校验存在
        validateMoldExists(mold.getId());
        // 更新
        moldMapper.updateById(mold);
    }

    @Override
    public void deleteMold(Long id) {
        // 校验存在
        validateMoldExists(id);
        // 删除
        moldMapper.deleteById(id);
    }

    @Override
    public MoldDO getMold(Long id) {
        MoldDO moldDO = moldMapper.selectById(id);
        Map<String,List<MoldRepairLineDO>> moldRepairDOMap=new HashMap<>();

        // 关联查询品牌表并补充字段
        if (moldDO != null && moldDO.getBrandId() != null) {
            MoldBrandDO moldBrandDO = moldBrandMapper.selectById(moldDO.getBrandId());
            if (moldBrandDO != null) {
                moldDO.setBrandName(moldBrandDO.getName());       // 品牌名称
                moldDO.setMoldType(moldBrandDO.getMoldType());   // 模具类型
                moldDO.setMoldSize(moldBrandDO.getMoldSize());   // 模具尺寸
                moldDO.setOrgType(moldBrandDO.getOrgType());     // 组织类型
            }
        }

        //点检列表
        List<MoldTicketResultsDO> inspectionList = moldticketResultsMapper.findByMoldIdAndPlanType(id, MoldPlanTypeEnum.INSPECTION.getCode(),null,null,null);
        if(CollectionUtils.isNotEmpty(inspectionList)){
            moldDO.setInspectionList(inspectionList);
        }

        //保养列表
        List<MoldTicketResultsDO> maintainList = moldticketResultsMapper.findByMoldIdAndPlanType(id, MoldPlanTypeEnum.MAINTENANCE.getCode(),null,null,null);
        if(CollectionUtils.isNotEmpty(maintainList)){
            moldDO.setMaintainList(maintainList);
        }

        //维修列表
        List<MoldRepairDO> moldRepairDOS = moldRepairMapperRepair.selectList(
                Wrappers.<MoldRepairDO>lambdaQuery()
                        .eq(MoldRepairDO::getMoldId, id));

        for (MoldRepairDO moldRepairDO : moldRepairDOS) {
            List<MoldRepairLineDO> moldRepairLineDOS = moldRepairLineMapper.selectList(Wrappers.<MoldRepairLineDO>lambdaQuery()
                    .eq(MoldRepairLineDO::getRepairId, moldRepairDO.getId())
                    .orderByDesc(MoldRepairLineDO::getCreateTime));
            if (!moldRepairLineDOS.isEmpty()) {
                // 修复JSON序列化null Key问题（保持原有风格的极简处理）
                String repairName = moldRepairDO.getRepairName();
                if (repairName == null || repairName.trim().isEmpty()) {
                    repairName = "维修单-" + moldRepairDO.getId();
                }
                moldRepairDOMap.put(repairName, moldRepairLineDOS);
            }
        }

        if(CollectionUtils.isNotEmpty(moldRepairDOMap)){
            moldDO.setRepairList(moldRepairDOMap);
        }

        return moldDO;
    }
    @Override
    public List<MoldDO> selectBy(MoldDO reqVO){
        return moldMapper.selectBy(reqVO);
    }
    private void validateMoldExists(Long id) {
        if (moldMapper.selectById(id) == null) {
            throw exception(MOLD_NOT_EXISTS);
        }
    }

    private void deleteMoldByBrandId(Long brandId) {
        moldMapper.deleteByBrandId(brandId);
    }

    // ==================== 子表（模具产品） ====================
    @Resource
    private MoldBrandProductMapper moldBrandProductMapper;
    @Override
    public PageResult<MoldBrandProductDO> getMoldBrandProductPage(PageParam pageReqVO, Long brandId) {
        return moldBrandProductMapper.selectPage(pageReqVO, brandId);
    }
    @Override
    public List<MoldProductRespVO> buildProduct(List<MoldBrandProductDO> list) {
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        Map<Long, ErpProductDO> map = productService.getProductMap(
                convertSet(list, MoldBrandProductDO::getProductId));
        return BeanUtils.toBean(list, MoldProductRespVO.class, item -> {
            MapUtils.findAndThen(map, item.getProductId(),
                    product -> item.setProductName(product.getName()));
        });
    }
    @Override
    public Long createMoldBrandProduct(MoldBrandProductDO moldBrandProduct) {
        MoldBrandProductDO resVo = new MoldBrandProductDO().setBrandId(moldBrandProduct.getBrandId())
                .setProductId(moldBrandProduct.getProductId());
        List<MoldBrandProductDO> list = moldBrandProductMapper.selectList(resVo);
        if(list!=null && list.size()>0){
            throw exception(MOLD_BRAND_PRODUCT_EXISTS);
        }
        moldBrandProductMapper.insert(moldBrandProduct);
        return moldBrandProduct.getId();
    }

    @Override
    public void updateMoldBrandProduct(MoldBrandProductDO moldBrandProduct) {
        // 校验存在
        validateMoldBrandProductExists(moldBrandProduct.getId());
        // 更新
        moldBrandProductMapper.updateById(moldBrandProduct);
    }

    @Override
    public void deleteMoldBrandProduct(Long id) {
        // 校验存在
        validateMoldBrandProductExists(id);
        // 删除
        moldBrandProductMapper.deleteById(id);
    }

    @Override
    public MoldBrandProductDO getMoldBrandProduct(Long id) {
        return moldBrandProductMapper.selectById(id);
    }

    @Override
    public List<MoldDO> getAllList() {
        return moldMapper.selectList();
    }

    @Override
    public List<MoldBrandDO> getMoldBrandList(Collection<Long> ids) {
        return moldBrandMapper.selectBatchIds(ids);
    }

    private void validateMoldBrandProductExists(Long id) {
        if (moldBrandProductMapper.selectById(id) == null) {
            throw exception(MOLD_BRAND_PRODUCT_NOT_EXISTS);
        }
    }

    private void deleteMoldBrandProductByBrandId(Long brandId) {
        moldBrandProductMapper.deleteByBrandId(brandId);
    }

    @Override
    public List<MoldBrandTreeRespVO> getMoldBrandTree() {
        // 1. 查询所有模具类型
        List<MoldBrandDO> allMoldBrands = moldBrandMapper.selectList();

        // 2. 构建树形结构
        return buildMoldBrandTree(allMoldBrands);
    }

    /**
     * 构建树形结构
     */
    private List<MoldBrandTreeRespVO> buildMoldBrandTree(List<MoldBrandDO> allMoldBrands) {
        return allMoldBrands.stream()
                .map(this::convertToTreeRespVO)
                .collect(Collectors.toList());
    }
    private MoldBrandTreeRespVO convertToTreeRespVO(MoldBrandDO moldBrand) {
        // 使用BeanUtils或手动设置属性
        MoldBrandTreeRespVO respVO = new MoldBrandTreeRespVO();

        // 复制公共属性（假设MoldBrandRespVO有对应的方法）
        BeanUtils.copyProperties(moldBrand, respVO);

        // 设置树状结构属性
        respVO.setChildren(new ArrayList<>());  // 空子节点
        respVO.setLeaf(true);                   // 叶子节点
        return respVO;
    }

}