package com.sw.mes.production.service.impl;


import com.alibaba.fastjson.JSON;
import com.sw.mes.core.base.BaseServiceImpl;
import com.sw.mes.core.context.BaseContextHandler;
import com.sw.mes.core.exception.BusinessException;
import com.sw.mes.core.response.ResultGenerator;
import com.sw.mes.core.utils.BeanUtil;
import com.sw.mes.production.dao.FormulaProductSchemeDao;
import com.sw.mes.production.dto.FormulaProductSchemeDto;
import com.sw.mes.production.entity.FormulaProductScheme;
import com.sw.mes.production.entity.FormulaProductSchemeDetail;
import com.sw.mes.production.entity.FormulaProductSchemeWeightDetail;
import com.sw.mes.production.service.FormulaProductSchemeDetailService;
import com.sw.mes.production.service.FormulaProductSchemeService;
import com.sw.mes.production.service.FormulaProductSchemeWeightDetailService;
import jodd.util.StringUtil;
import org.modelmapper.ModelMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @Author
 * @Description：
 * @Date: Create in
 * @Modified By:
 */
@Service
@Transactional
public class FormulaProductSchemeServiceImpl extends BaseServiceImpl<FormulaProductScheme> implements FormulaProductSchemeService {
    FormulaProductSchemeDao dao;

    @Autowired
    public void setDao(FormulaProductSchemeDao dao) {
        super.setBaseDao(dao);
        this.dao = dao;
    }

    @Autowired
    ModelMapper modelMapper;

    @Autowired
    private FormulaProductSchemeDetailService productSchemeDetailService;

    @Autowired
    private FormulaProductSchemeWeightDetailService productSchemeWeightDetailService;

    @Override
    public FormulaProductScheme findByEquipmentCodeAndProductModeCode(String equipmentCode, String productModeCode) {
        return dao.findByEquipmentCodeAndProductModeCode(equipmentCode, productModeCode);
    }

    @Override
    public void update(FormulaProductSchemeDto dto,  FormulaProductScheme entity) {
        List<FormulaProductSchemeWeightDetail> weightDetailList = dto.getWeightDetailList();
        FormulaProductScheme entityfromFto = fromDto(dto);
        if (dto.getStatus() == 0) {
            BeanUtils.copyProperties(entityfromFto, entity, BeanUtil.getIgnoreProperties(entityfromFto, null, null));
            // 更新明细
            productSchemeDetailService.deleteByFpsId(entity.getId());
            productSchemeWeightDetailService.deleteByFpsId(entity.getId());

            for (FormulaProductSchemeWeightDetail weightDetail : weightDetailList) {
                weightDetail.setFormulaProductSchemeId(entity.getId());
                for (FormulaProductSchemeDetail schemeDetail : weightDetail.getSchemeDetailList()) {
                    schemeDetail.setFormulaProductSchemeId(entity.getId());
                }
                productSchemeDetailService.saveAll(weightDetail.getSchemeDetailList());
            }
            productSchemeWeightDetailService.saveAll(weightDetailList);
        } else {
            entity.setStatus(0);
            entity.setNextFurnaceEffective(JSON.toJSONString(dto));
        }
        entity.setGmtUpdate(new Date());
        entity.setUserUpdate(BaseContextHandler.getUsername());
        this.saveOrUpdate(entity);
    }

    @Override
    public List<FormulaProductScheme> creates(List<FormulaProductScheme> formulaProductSchemes) {
        Map<String, List<FormulaProductScheme>> formulaProductSchemeMap = formulaProductSchemes.stream().collect(Collectors.groupingBy(formulaProductScheme -> formulaProductScheme.getEquipmentCode() + formulaProductScheme.getProductModeCode(), Collectors.toList()));
        formulaProductSchemeMap.values().forEach(formulaProductSchemeList -> {
            Assert.isTrue(formulaProductSchemeList.size() == 1, "【" + formulaProductSchemeList.get(0).getEquipmentCode() + "/" + formulaProductSchemeList.get(0).getProductModeCode() + "】同一设备同一产品，只能有一条配方");
        });
        List<FormulaProductScheme> formulaProductSchemeList = new ArrayList<>();
        formulaProductSchemes.forEach(formulaProductScheme -> {
            FormulaProductScheme formulaProductSchemeOld = findByEquipmentCodeAndProductModeCode(formulaProductScheme.getEquipmentCode(),
                    formulaProductScheme.getProductModeCode());
            if (formulaProductSchemeOld != null) {
                if (formulaProductScheme.getStatus() == null) {
                    formulaProductSchemeList.add(formulaProductScheme);
                } else {
                    if (formulaProductScheme.getStatus() == 0) {
                        formulaProductScheme.setId(formulaProductSchemeOld.getId());
                        BeanUtils.copyProperties(formulaProductScheme, formulaProductSchemeOld, BeanUtil.getIgnoreProperties(formulaProductScheme, null, null));
                        formulaProductScheme = formulaProductSchemeOld;
                    } else {
                        FormulaProductScheme formulaProductSchemeNew = new FormulaProductScheme();
                        BeanUtils.copyProperties(formulaProductScheme, formulaProductSchemeNew);
                        formulaProductScheme = formulaProductSchemeOld;
                        formulaProductScheme.setNextFurnaceEffective(JSON.toJSONString(formulaProductSchemeNew));
                    }
                    formulaProductScheme.setGmtUpdate(new Date());
                    formulaProductScheme.setUserUpdate(BaseContextHandler.getUsername());
                }
            } else {
                formulaProductScheme.setGmtCreate(new Date());
                formulaProductScheme.setUserCreate(BaseContextHandler.getUsername());
                formulaProductScheme.setStatus(0);
            }
        });

        if (formulaProductSchemeList.size() > 0) {
            return formulaProductSchemeList;
        } else {
            saveAll(formulaProductSchemes);
            return new ArrayList<>();
        }
    }

    @Override
    public List<FormulaProductSchemeDto> createsV2(List<FormulaProductSchemeDto> dtoList) {
        Map<String, List<FormulaProductSchemeDto>> dtoMap = dtoList.stream().collect(Collectors.groupingBy(formulaProductScheme -> formulaProductScheme.getEquipmentCode() + formulaProductScheme.getProductModeCode(), Collectors.toList()));
        dtoMap.values().forEach(formulaProductSchemeList -> {
            Assert.isTrue(formulaProductSchemeList.size() == 1, "【" + formulaProductSchemeList.get(0).getEquipmentCode() + "/" + formulaProductSchemeList.get(0).getProductModeCode() + "】同一设备同一产品，只能有一条配方");
        });
        for (FormulaProductSchemeDto dto : dtoList) {
            List<FormulaProductSchemeWeightDetail> weightDetailList = dto.getWeightDetailList();
            Assert.notEmpty(weightDetailList, "设备【"+dto.getEquipmentCode()+"】料号【"+dto.getProductModeCode()+"】拆桶方案不能为空");
            for (FormulaProductSchemeWeightDetail weightDetail : weightDetailList) {
                List<FormulaProductSchemeDetail> schemeDetailList = weightDetail.getSchemeDetailList();
                Assert.notEmpty(schemeDetailList, "设备【"+dto.getEquipmentCode()+"】料号【"+dto.getProductModeCode()+"】拆桶方案【"+weightDetail.getWeightSchemeName()+"】配方方案不能为空");
                String checkAgainNumMsg = checkAgainNum(schemeDetailList);
                if (StringUtil.isNotBlank(checkAgainNumMsg)){
                    throw new BusinessException("设备【"+dto.getEquipmentCode()+"】料号【"+dto.getProductModeCode()+"】拆桶方案【"+weightDetail.getWeightSchemeName()+"】" + checkAgainNumMsg);
                }
            }
        }

        List<FormulaProductSchemeDto> formulaProductSchemeList = new ArrayList<>();
        dtoList.forEach(dto -> {
            FormulaProductScheme entity = findByEquipmentCodeAndProductModeCode(dto.getEquipmentCode(),
                    dto.getProductModeCode());
            FormulaProductScheme formulaProductScheme = this.fromDto(dto);
            if (entity != null) {
                if (dto.getStatus() == null) {
                    formulaProductSchemeList.add(dto);
                } else {
                    if (dto.getStatus() == 0) {
                        BeanUtils.copyProperties(formulaProductScheme, entity, BeanUtil.getIgnoreProperties(formulaProductScheme, null, null));
                        // 更新明细
                        productSchemeDetailService.deleteByFpsId(entity.getId());
                        productSchemeWeightDetailService.deleteByFpsId(entity.getId());

                        for (FormulaProductSchemeWeightDetail weightDetail : dto.getWeightDetailList()) {
                            weightDetail.setFormulaProductSchemeId(entity.getId());
                            for (FormulaProductSchemeDetail schemeDetail : weightDetail.getSchemeDetailList()) {
                                schemeDetail.setFormulaProductSchemeId(entity.getId());
                            }
                            productSchemeDetailService.saveAll(weightDetail.getSchemeDetailList());
                        }
                        productSchemeWeightDetailService.saveAll(dto.getWeightDetailList());
                    } else {
                        entity.setStatus(0);
                        entity.setNextFurnaceEffective(JSON.toJSONString(dto));
                    }
                    entity.setGmtUpdate(new Date());
                    entity.setUserUpdate(BaseContextHandler.getUsername());

                    // 保存
                    this.saveOrUpdate(entity);
                }
            } else {
                formulaProductScheme.setGmtCreate(new Date());
                formulaProductScheme.setUserCreate(BaseContextHandler.getUsername());
                formulaProductScheme.setStatus(0);

                this.saveOrUpdate(formulaProductScheme);
                for (FormulaProductSchemeWeightDetail weightDetail : dto.getWeightDetailList()) {
                    // 重量方案
                    weightDetail.setFormulaProductSchemeId(formulaProductScheme.getId());
                    productSchemeWeightDetailService.saveOrUpdate(weightDetail);

                    // 配方方案
                    List<FormulaProductSchemeDetail> detailList = weightDetail.getSchemeDetailList();
                    for (FormulaProductSchemeDetail detail : detailList) {
                        detail.setFormulaProductSchemeId(formulaProductScheme.getId());
                    }
                    productSchemeDetailService.saveAll(detailList);
                }
            }
        });

        if (formulaProductSchemeList.size() > 0) {
            return formulaProductSchemeList;
        } else {
            return new ArrayList<>();
        }
    }

    @Override
    public void create(FormulaProductSchemeDto formulaProductSchemeDto) {
        List<FormulaProductSchemeWeightDetail> weightDetailList = formulaProductSchemeDto.getWeightDetailList();
        Assert.notEmpty(weightDetailList, "重量方案不能为空");

        for (FormulaProductSchemeWeightDetail weightDetail : weightDetailList) {
            List<FormulaProductSchemeDetail> detailList = weightDetail.getSchemeDetailList();
            Assert.notEmpty(detailList, "拆桶方案【"+weightDetail.getWeightSchemeName()+"】中配方方案不能为空");
            String checkAgainNumMsg = this.checkAgainNum(detailList);
            if (StringUtil.isNotBlank(checkAgainNumMsg)){
                throw new BusinessException(checkAgainNumMsg);
            }
        }

        FormulaProductScheme productScheme = fromDto(formulaProductSchemeDto);
        productScheme.setStatus(0);
        productScheme.setGmtCreate(new Date());
        productScheme.setUserCreate(BaseContextHandler.getUsername());
        this.saveOrUpdate(productScheme);

        for (FormulaProductSchemeWeightDetail weightDetail : weightDetailList) {
            // 重量方案
            weightDetail.setFormulaProductSchemeId(productScheme.getId());
            productSchemeWeightDetailService.saveOrUpdate(weightDetail);

            // 配方方案
            List<FormulaProductSchemeDetail> detailList = weightDetail.getSchemeDetailList();
            for (FormulaProductSchemeDetail detail : detailList) {
                detail.setFormulaProductSchemeId(productScheme.getId());
            }
            productSchemeDetailService.saveAll(detailList);
        }
    }

    @Override
    public void createBatch(FormulaProductSchemeDto dto) {
        if (CollectionUtils.isEmpty(dto.getEquipmentCodeList())){
            throw new BusinessException("设备不能为空");
        }
        List<FormulaProductSchemeWeightDetail> weightDetailList = dto.getWeightDetailList();
        if (CollectionUtils.isEmpty(weightDetailList)){
            throw new BusinessException("拆桶方案不能为空");
        }
        for (FormulaProductSchemeWeightDetail weightDetail : weightDetailList) {
            String checkAgainNumMsg = checkAgainNum(weightDetail.getSchemeDetailList());
            if (StringUtil.isNotBlank(checkAgainNumMsg)){
                throw new BusinessException(checkAgainNumMsg);
            }
        }
        for (String code : dto.getEquipmentCodeList()) {
            FormulaProductScheme entity = this.findByEquipmentCodeAndProductModeCode(code, dto.getProductModeCode());
            if (!ObjectUtils.isEmpty(entity)){
                throw new BusinessException("设备【"+code+"】下已存在产品【"+dto.getProductName()+"】的配方方案");
            }
        }

        // 保存明细
        for (String code : dto.getEquipmentCodeList()) {
            FormulaProductScheme scheme = fromDto(dto);
            scheme.setEquipmentCode(code);
            scheme.setStatus(0);
            scheme.setGmtCreate(new Date());
            scheme.setUserCreate(BaseContextHandler.getUsername());
            this.saveOrUpdate(scheme);

            for (FormulaProductSchemeWeightDetail weightDetail : weightDetailList) {
                // 重量方案
                weightDetail.setFormulaProductSchemeId(scheme.getId());
                productSchemeWeightDetailService.saveOrUpdate(weightDetail);

                // 配方方案
                List<FormulaProductSchemeDetail> detailList = weightDetail.getSchemeDetailList();
                for (FormulaProductSchemeDetail detail : detailList) {
                    detail.setFormulaProductSchemeId(scheme.getId());
                }
                productSchemeDetailService.saveAll(detailList);
            }
        }
    }

    @Override
    public String checkAgainNum(List<FormulaProductSchemeDetail> detailList) {
        detailList.sort(Comparator.comparingInt(FormulaProductSchemeDetail::getAgainNum));
        Integer index = 0;
        boolean checkStart = false;
        boolean checkEnd = false;
        for (int i = 0; i < detailList.size(); i++) {
            FormulaProductSchemeDetail detail = detailList.get(i);
            if (0 == detail.getAgainNum()){
                checkStart = true;
            } else if (99 == detail.getAgainNum()){
                checkEnd = true;
            }else {
                if (!index.equals(detail.getAgainNum())){
                    return "加次【"+index+"】配方未配置";
                }
            }
            index++;
        }
        if (!checkStart) return "初装配方未配置";
        if (!checkEnd) return "完结配方未配置";
        return null;
    }


    public FormulaProductScheme fromDto(FormulaProductSchemeDto dto) {
        return modelMapper.map(dto, FormulaProductScheme.class);
    }

}
