package com.fjhx.sale.flow;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.*;
import com.fjhx.area.utils.CustomizeAreaUtil;
import com.fjhx.common.enums.FlowStatusEnum1;
import com.fjhx.common.utils.Assert;
import com.fjhx.file.utils.ObsFileUtil;
import com.fjhx.flow.core.FlowDelegate;
import com.fjhx.flow.enums.FlowStatusEnum;
import com.fjhx.sale.entity.sample.dto.SampleDto;
import com.fjhx.sale.entity.sample.po.Sample;
import com.fjhx.sale.entity.sample.po.SampleProduct;
import com.fjhx.sale.entity.sample.po.SampleProject;
import com.fjhx.sale.entity.sample.po.SampleShipment;
import com.fjhx.sale.service.sample.SampleProductService;
import com.fjhx.sale.service.sample.SampleProjectService;
import com.fjhx.sale.service.sample.SampleService;
import com.fjhx.sale.service.sample.SampleShipmentService;
import com.ruoyi.common.core.domain.BasePo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 样品单变更流程
 */
@Component
//@DS(SourceConstant.SALE)
public class SampleUpdateFlow extends FlowDelegate {
//
//    @Autowired
//    private SampleFlow sampleFlow;

    @Autowired
    private SampleService sampleService;

    @Autowired
    private SampleProductService sampleProductService;

    @Autowired
    private SampleProjectService sampleProjectService;

    @Autowired
    private SampleShipmentService sampleShipmentService;

    @Override
    public String getFlowKey() {
        return "sample_update_flow";
    }

    /**
     * 发起流程
     *
     * @param flowId     流程ID
     * @param submitData 样品单数据
     * @return
     */
    @Override
    public Long start(Long flowId, JSONObject submitData) {

        SampleDto newSample = submitData.toJavaObject(SampleDto.class);
        //赋值流程id
        newSample.setFlowId(flowId);

        //判断合同是否在变更中，防止用户缓存导致重复变更
        Sample byId = sampleService.getById(newSample.getOldSampleId());
        Assert.notEmpty(byId, "查询不到样品单信息");
        if (byId.getStatus().equals(FlowStatusEnum1.UPDATE_LOADING.getKey())) {
            throw new ServiceException("样品单正在变更中，禁止重复变更！");
        }

        // 原样品单id不能为空
        Long oldSampleId = newSample.getOldSampleId();
        if (oldSampleId == null) {
            throw new ServiceException("原样品单id不能为空");
        }
        //查询原样品单
        Sample oldSample = sampleService.getById(newSample.getOldSampleId());
        if (ObjectUtil.isEmpty(oldSample)) {
            throw new ServiceException("查询不到原样品单信息");
        }
        //更新原样品单状态为变更中
        oldSample.setStatus(FlowStatusEnum1.UPDATE_LOADING.getKey());
        sampleService.updateById(oldSample);
        //查询旧样品单的订单产品
        List<SampleProduct> oldSampleProductList = sampleProductService.list(q -> q.eq(SampleProduct::getSampleId, oldSampleId));
        if (CollectionUtils.isEmpty(oldSampleProductList)) {
            throw new ServiceException("原样品单没有产品");
        }
        Map<Long, List<SampleProduct>> oldSampleMap = oldSampleProductList.stream().collect(Collectors.groupingBy(SampleProduct::getId));
        List<SampleProduct> newSampleProductList = newSample.getSampleProductList();
        if (CollectionUtils.isEmpty(newSampleProductList)) {
            throw new ServiceException("变更样品单产品不能为空");
        }
        /**
         * 赋值新的变更样品单号
         */
        String code = oldSample.getCode();
        Matcher matcher = Pattern.compile(".*\\((.*?)\\)$").matcher(code);
        int index = 2;
        if (matcher.find()) {
            index = (Integer.parseInt(matcher.group(1)) + 1);
            code = code.substring(0, code.lastIndexOf("("));
        }
        newSample.setCode(code + "(" + index + ")");
        newSample.setIsShow(1);//隐藏样品单
        /**
         * 计算新样品单的剩余数量
         */
        for (SampleProduct newCp : newSampleProductList) {
            newCp.setExpendQuantity(newCp.getQuantity());
            if (ObjectUtil.isNotEmpty(newCp.getId())) {//如果新样品单产品ID不为空
                //取出旧样品单
                SampleProduct oldSampleProduct = oldSampleMap.getOrDefault(newCp.getId(), null).get(0);
                //取出旧样品单包装方式
                JSONObject oldJson = JSONObject.parseObject(oldSampleProduct.getEhsdJson());
                String oldPackMethod = oldJson.getOrDefault("packMethod", null) == null ? null : oldJson.getOrDefault("packMethod", null).toString();
                //取出新样品单包装方式
                JSONObject newJson = JSONObject.parseObject(newCp.getEhsdJson());
                String newPackMethod = newJson.getOrDefault("packMethod", null) == null ? null : oldJson.getOrDefault("packMethod", null).toString();
                /**
                 * 商品英文名、尺寸、包装方式、数量 没有变更---取原本的剩余数量
                 */
                if (oldSampleProduct.getQuantity().compareTo(newCp.getQuantity()) == 0
                        && StringUtils.equals(oldSampleProduct.getProductName(), newCp.getProductName())
                        && StringUtils.equals(oldSampleProduct.getProductModel(), newCp.getProductModel())
                        && StringUtils.equals(oldPackMethod, newPackMethod)) {
                    //取出旧的剩余数量
                    newCp.setExpendQuantity(oldSampleProduct.getExpendQuantity());
                }
            }
        }
        long sampleId = update(newSample);
//        if(newSample.getStartType()==1){//直接审批通过
//            this.end(flowId,sampleId,submitData);
//        }
        return sampleId;
    }

    /**
     * 结束流程
     *
     * @param flowId     流程ID
     * @param businessId 业务ID
     * @param submitData 数据
     */
    @Override
    public void end(Long flowId, Long businessId, JSONObject submitData) {
        // 通过业务ID查询样品单数据
        Sample newSample = sampleService.getById(businessId);
        if (ObjectUtils.isEmpty(newSample)) {
            throw new ServiceException("样品单不存在");
        }
        long oldSampleId = newSample.getOldSampleId();//取出旧的样品单ID
        Sample oldSample = sampleService.getById(oldSampleId);
        if (oldSample == null) {
            throw new ServiceException("原样品单不存在");
        }
        long temOldId = IdWorker.getId();
        long temNewId = IdWorker.getId();
        Sample temOldUpSample = new Sample();
        temOldUpSample.setId(temOldId);
        temOldUpSample.setUpId(oldSampleId);
        Sample temNewUpSample = new Sample();
        temNewUpSample.setId(temNewId);
        temNewUpSample.setUpId(businessId);
        //替换新旧数据ID为临时ID
        sampleService.updateSample(temOldUpSample);
        sampleService.updateSample(temNewUpSample);
        //查询新数据产品、收费、出货
        List<Long> newSampleProductIds = sampleProductService.list(Wrappers.<SampleProduct>query().lambda().select(SampleProduct::getId).eq(SampleProduct::getSampleId, businessId)).stream().map(SampleProduct::getId).collect(Collectors.toList());
        List<Long> newSampleProjectIds = sampleProjectService.list(Wrappers.<SampleProject>query().lambda().select(SampleProject::getId).eq(SampleProject::getSampleId, businessId)).stream().map(SampleProject::getId).collect(Collectors.toList());
        List<Long> newSampleShipmentIds = sampleShipmentService.list(Wrappers.<SampleShipment>query().lambda().select(SampleShipment::getId).eq(SampleShipment::getSampleId, businessId)).stream().map(SampleShipment::getId).collect(Collectors.toList());


        //查询旧数据产品、收费、出货
        List<Long> oldSampleProductIds = sampleProductService.list(Wrappers.<SampleProduct>query().lambda().select(SampleProduct::getId).eq(SampleProduct::getSampleId, oldSampleId)).stream().map(SampleProduct::getId).collect(Collectors.toList());
        List<Long> oldSampleProjectIds = sampleProjectService.list(Wrappers.<SampleProject>query().lambda().select(SampleProject::getId).eq(SampleProject::getSampleId, oldSampleId)).stream().map(SampleProject::getId).collect(Collectors.toList());
        List<Long> oldSampleShipmentIds = sampleShipmentService.list(Wrappers.<SampleShipment>query().lambda().select(SampleShipment::getId).eq(SampleShipment::getSampleId, oldSampleId)).stream().map(SampleShipment::getId).collect(Collectors.toList());

        /**
         * 处理新样品单---
         */
        newSample.setId(oldSampleId);//id赋值为旧样品单的id
        newSample.setStatus(FlowStatusEnum1.PASS.getKey());
        newSample.setApprovedDate(new Date());
        newSample.setUpId(temNewId);
        newSample.setOldSampleId(businessId);
        newSample.setIsShow(0);//显示新样品单
        sampleService.updateSample(newSample);
        //修改样品单产品相关数据
        if (CollectionUtils.isNotEmpty(newSampleProductIds)) {
            sampleProductService.update(Wrappers.<SampleProduct>update().lambda().set(SampleProduct::getSampleId, oldSampleId).in(SampleProduct::getId, newSampleProductIds));
        }
        //修改样品单收费相关数据
        if (CollectionUtils.isNotEmpty(newSampleProjectIds)) {
            sampleProjectService.update(Wrappers.<SampleProject>update().lambda().set(SampleProject::getSampleId, oldSampleId).in(SampleProject::getId, newSampleProjectIds));
        }
        //修改样品单出货相关数据
        if (CollectionUtils.isNotEmpty(newSampleShipmentIds)) {
            sampleShipmentService.update(Wrappers.<SampleShipment>update().lambda().set(SampleShipment::getSampleId, oldSampleId).in(SampleShipment::getId, newSampleShipmentIds));
        }
        /**
         * 处理旧的样品单---
         */
        oldSample.setId(businessId);
        oldSample.setStatus(FlowStatusEnum1.UPDATE.getKey());
        oldSample.setIsChange("1");
        oldSample.setUpId(temOldId);
        oldSample.setIsShow(1);//隐藏旧的样品单
        sampleService.updateSample(oldSample);
        //修改样品单产品相关数据
        if (CollectionUtils.isNotEmpty(oldSampleProductIds)) {
            sampleProductService.update(Wrappers.<SampleProduct>update().lambda().set(SampleProduct::getSampleId, businessId).in(SampleProduct::getId, oldSampleProductIds));
        }
        //修改样品单收费相关数据
        if (CollectionUtils.isNotEmpty(oldSampleProjectIds)) {
            sampleProjectService.update(Wrappers.<SampleProject>update().lambda().set(SampleProject::getSampleId, businessId).in(SampleProject::getId, oldSampleProjectIds));
        }
        //修改样品单出货相关数据
        if (CollectionUtils.isNotEmpty(oldSampleShipmentIds)) {
            sampleShipmentService.update(Wrappers.<SampleShipment>update().lambda().set(SampleShipment::getSampleId, businessId).in(SampleShipment::getId, oldSampleShipmentIds));
        }
        ObsFileUtil.exchangeBusinessId(oldSampleId, businessId);
    }

    /**
     * 变更数据
     *
     * @param sample
     * @return
     */
    public Long update(SampleDto sample) {
        //赋值城市省份信息
        CustomizeAreaUtil.setAreaId(sample);
        sample.setBuyCityId(sample.getCityId());
        sample.setBuyCountryId(sample.getCountryId());
        sample.setBuyProvinceId(sample.getProvinceId());
//        sample.setCode(CodeEnum.SAMPLE_CODE.getCode());
        sample.setStatus(FlowStatusEnum1.UNDER_REVIEW.getKey());
        sample.setUserName(SecurityUtils.getUsername());

        sampleService.save(sample);
        List<SampleProduct> sampleProductList = sample.getSampleProductList();
        if (CollectionUtils.isNotEmpty(sampleProductList)) {//保存样品单产品
            for (SampleProduct c : sampleProductList) {
                c.setId(IdWorker.getId());
                c.setSampleId(sample.getId());
                c.setExpendQuantity(c.getQuantity());
            }
            sampleProductService.saveBatch(sampleProductList);
        }
        List<SampleProject> sampleProjectList = sample.getSampleProjectList();
        if (CollectionUtils.isNotEmpty(sampleProjectList)) {//保存收费项目
            for (SampleProject c : sampleProjectList) {
                c.setId(IdWorker.getId());
                c.setSampleId(sample.getId());
            }
            sampleProjectService.saveBatch(sampleProjectList);
        }
        List<SampleShipment> sampleShipmentList = sample.getSampleShipmentList();
        if (CollectionUtils.isNotEmpty(sampleShipmentList)) {//保存自定义出货
            for (SampleShipment c : sampleShipmentList) {
                c.setId(IdWorker.getId());
                c.setSampleId(sample.getId());
            }
            sampleShipmentService.saveBatch(sampleShipmentList);
        }
        //交接单附件
        ObsFileUtil.copyFileAndSave(sample.getFileList(), sample.getId(), 1);
        //包装附件
        ObsFileUtil.copyFileAndSave(sample.getPackageFileList(), sample.getId(), 2);
        return sample.getId();
    }

    /**
     * 驳回
     */
    @Override
    public void reject(Long flowId, Long businessId, FlowStatusEnum flowStatus) {
        super.reject(flowId, businessId, flowStatus);

        Sample sample = sampleService.getById(businessId);
        sampleService.update(q -> q
                .eq(Sample::getId, businessId)
                .set(Sample::getStatus, FlowStatusEnum1.REJECT.getKey())
                .set(Sample::getUpdateTime, new Date())
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );
        //恢复原合同状态
        sampleService.update(q -> q
                .eq(Sample::getId, sample.getOldSampleId())
                .set(Sample::getStatus, FlowStatusEnum1.PASS.getKey())
                .set(Sample::getUpdateTime, new Date())
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );
    }

    /**
     * 重新发起
     */
    @Override
    public void relaunch(Long flowId, Long businessId, FlowStatusEnum flowStatus, JSONObject submitData) {
//        sampleFlow.relaunch(flowId, businessId, flowStatus, submitData);
    }

    /**
     * 作废
     */
    @Override
    public void cancellation(Long flowId, Long businessId, FlowStatusEnum flowStatus) {
//        sampleFlow.cancellation(flowId, businessId, flowStatus);
        //恢复原合同状态
        Sample sample = sampleService.getById(businessId);
        sampleService.update(q -> q
                .eq(Sample::getId, sample.getOldSampleId())
                .set(Sample::getStatus, FlowStatusEnum1.PASS.getKey())
                .set(Sample::getUpdateTime, new Date())
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );
    }
}
