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

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.common.utils.Assert;
import com.fjhx.item.entity.product.po.ProductInfo;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.mes.entity.applicable.po.ApplicableProducts;
import com.fjhx.mes.entity.production.dto.ProductionTaskDetailDto;
import com.fjhx.mes.entity.production.dto.ProductionTaskDetailSelectDto;
import com.fjhx.mes.entity.production.po.*;
import com.fjhx.mes.entity.production.vo.ProductionTaskDetailVo;
import com.fjhx.mes.entity.technology.po.Technology;
import com.fjhx.mes.entity.work.po.WorkOrder;
import com.fjhx.mes.entity.work.po.WorkOrderProductionProcesses;
import com.fjhx.mes.entity.work.vo.WorkOrderVo;
import com.fjhx.mes.mapper.production.ProductionTaskDetailMapper;
import com.fjhx.mes.service.applicable.ApplicableProductsService;
import com.fjhx.mes.service.production.*;
import com.fjhx.mes.service.technology.TechnologyService;
import com.fjhx.mes.service.work.WorkOrderProductionProcessesService;
import com.fjhx.mes.service.work.WorkOrderService;
import com.fjhx.wms.entity.stock.emums.JournalType;
import com.fjhx.wms.entity.stock.po.StockWait;
import com.fjhx.wms.entity.stock.po.StockWaitDetails;
import com.fjhx.wms.service.stock.StockWaitDetailsService;
import com.fjhx.wms.service.stock.StockWaitService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.wrapper.IWrapper;
import com.ruoyi.system.utils.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * <p>
 * 生产任务明细 服务实现类
 * </p>
 *
 * @author
 * @since 2023-05-18
 */
@Service
public class ProductionTaskDetailServiceImpl extends ServiceImpl<ProductionTaskDetailMapper, ProductionTaskDetail> implements ProductionTaskDetailService {
    @Autowired
    private ProductionTaskDetailRecordService productionTaskDetailRecordService;
    @Autowired
    private ProductionTaskService productionTaskService;
    @Autowired
    private ProductionPlanService productionPlanService;
    @Autowired
    private WorkOrderService workOrderService;
    @Autowired
    private WorkOrderProductionProcessesService workOrderProductionProcessesService;
    @Autowired
    private ApplicableProductsService applicableProductsService;
    @Autowired
    private TechnologyService technologyService;
    @Autowired
    private StockWaitService stockWaitService;
    @Autowired
    private StockWaitDetailsService stockWaitDetailsService;
    @Autowired
    private ProductInfoService productInfoService;
    @Autowired
    private ProductionProcessesService productionProcessesService;

    @Override
    public Page<ProductionTaskDetailVo> getPage(ProductionTaskDetailSelectDto dto) {
        IWrapper<ProductionTaskDetail> wrapper = getWrapper();
        return pageCom(wrapper, dto);
    }

    @Override
    public Page<ProductionTaskDetailVo> circulationPage(ProductionTaskDetailSelectDto dto) {
        IWrapper<ProductionTaskDetail> wrapper = getWrapper();
        //过滤负责人为自己的任务
        wrapper.eq(ProductionTaskDetail::getPersonLiableId, SecurityUtils.getUserId());
        //过滤未在流转的记录
        wrapper.eq(ProductionTaskDetail::getCirculationStatus,0);
        //过滤未完成的记录
        wrapper.eq(ProductionTaskDetail::getFinishStatus,0);
        return pageCom(wrapper, dto);
    }

    /**
     * 分页公共方法
     */
    Page<ProductionTaskDetailVo> pageCom(IWrapper<ProductionTaskDetail> wrapper, ProductionTaskDetailSelectDto dto) {
        //关键字搜索
        if (ObjectUtil.isNotEmpty(dto.getKeyword())){
            List<Long> productIds = productInfoService.listObject(ProductInfo::getId, q -> q.like(ProductInfo::getName, dto.getKeyword()));
            wrapper.and(q->q.in(ProductionTaskDetail::getProductId,productIds).or().like(ProductionTaskDetail::getProductSn,dto.getKeyword()));
        }

        wrapper.orderByDesc("ptd", ProductionTaskDetail::getId);
        Page<ProductionTaskDetailVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<ProductionTaskDetailVo> records = page.getRecords();
        if(ObjectUtil.isEmpty(records)){
            return new Page<>();
        }
        //赋值流转人名称
        UserUtil.assignmentNickName(records, ProductionTaskDetailVo::getCirculationUserId, ProductionTaskDetailVo::setCirculationUserName);

        //赋值产品名
        productInfoService.attributeAssign(records, ProductionTaskDetailVo::getProductId, (item, productInfo) -> {
            item.setProductName(productInfo.getName());
        });
        //赋值当前工序名 目标工序名
        List<Long> productionTaskIds = records.stream().map(ProductionTaskDetail::getProductionTaskId).collect(Collectors.toList());
        IWrapper<ProductionTaskDetail> wrapper1 = IWrapper.getWrapper();
        wrapper1.in("pt", ProductionTaskDetail::getId, productionTaskIds);
        wrapper1.groupBy("wo.id");
        List<WorkOrderVo> workOrderByProductionTask = baseMapper.getWorkOrderByProductionTask(wrapper1);
        Map<Long, WorkOrderVo> WorkOrderMap = workOrderByProductionTask.stream().collect(Collectors.toMap(WorkOrderVo::getProductionTaskId, Function.identity()));
        List<Long> workIds = workOrderByProductionTask.stream().map(WorkOrderVo::getId).collect(Collectors.toList());

        //获取工序id列表
        List<Long> productionProcessesIds = records.stream().map(ProductionTaskDetail::getProductionProcessesId).collect(Collectors.toList());
        productionProcessesIds.addAll(records.stream().map(ProductionTaskDetail::getNextProductionProcessesId).collect(Collectors.toList()));
        //获取基本工序map
        Map<Long, String> stringMap = productionProcessesService.mapKV(ProductionProcesses::getId, ProductionProcesses::getName,
                q -> q.in(ProductionProcesses::getId, productionProcessesIds));
        //获取定制工序map
        Map<Long, String> workOrderProductionPMap = workOrderProductionProcessesService.mapKV(WorkOrderProductionProcesses::getId,
                WorkOrderProductionProcesses::getName, q -> q.in(WorkOrderProductionProcesses::getWorkOrderId, workIds));

        for (ProductionTaskDetailVo record : records) {
            WorkOrderVo workOrderVo = WorkOrderMap.get(record.getProductionTaskId());
            if ("1".equals(workOrderVo.getIsCustomized())) {
                //如果是定制
                String name = workOrderProductionPMap.get(record.getProductionProcessesId());
                String nextName = workOrderProductionPMap.get(record.getNextProductionProcessesId());
                record.setProductionProcessesName(name);
                record.setNextProductionProcessesName(nextName);
            } else {
                //不是定制
                String name = stringMap.get(record.getProductionProcessesId());
                String nextName = stringMap.get(record.getNextProductionProcessesId());
                record.setProductionProcessesName(name);
                record.setNextProductionProcessesName(nextName);
            }
        }

        return page;
    }

    /**
     * 任务流转
     */
    @Override
    public void circulation(ProductionTaskDetailDto productionTaskDetailDto) {
        //修改流转状态
        productionTaskDetailDto.setCirculationStatus(1);
        //赋值接收人id
        productionTaskDetailDto.setReceivedUserId(productionTaskDetailDto.getReceivedUserId());
        //赋值流转人id
        productionTaskDetailDto.setCirculationUserId(SecurityUtils.getUserId());
        this.updateById(productionTaskDetailDto);
    }

    /**
     * 完工入库
     */
    @Override
    public void productStorage(Long id) {
        ProductionTaskDetail productionTaskDetail = getById(id);
        if (ObjectUtil.isEmpty(productionTaskDetail)) {
            throw new ServiceException("未查询到任务明细信息");
        }
        productionTaskDetail.setFinishStatus(1);//标记为完成
        productionTaskDetail.setFinishTime(new Date());//记录完成时间
        this.updateById(productionTaskDetail);

        StockWait stockWait = new StockWait();
        stockWait.setType(1);//入库
        stockWait.setStatus(0);//待入库
        stockWait.setBusinessType(JournalType.COMPLETION_IN.getDetailType());//
        stockWait.setBusinessId(productionTaskDetail.getId());//生产任务明细id
        stockWait.setBusinessCode(productionTaskDetail.getProductSn());//产品sn
        stockWaitService.save(stockWait);
        StockWaitDetails stockWaitDetails = new StockWaitDetails();
        stockWaitDetails.setStockWaitId(stockWait.getId());
        stockWaitDetails.setProductId(productionTaskDetail.getProductId());
        stockWaitDetails.setQuantity(BigDecimal.ONE);//生产任务明细入库 数量默认只有1
        stockWaitDetailsService.save(stockWaitDetails);
    }

    /**
     * 任务接收分页
     */
    @Override
    public Page<ProductionTaskDetailVo> receivePage(ProductionTaskDetailSelectDto dto) {
        IWrapper<ProductionTaskDetail> wrapper = getWrapper();
        //过滤接收人为自己的任务
        wrapper.eq(ProductionTaskDetail::getReceivedUserId, SecurityUtils.getUserId());
        return pageCom(wrapper, dto);
    }

    /**
     * 任务接收
     */
    @Override
    public void receive(ProductionTaskDetailDto productionTaskDetailDto) {
        ProductionTaskDetail productionTaskDetail = getById(productionTaskDetailDto.getId());

        //修改流转状态
        productionTaskDetail.setCirculationStatus(0);
        //将下一工序赋值到当前工序
        productionTaskDetail.setProductionProcessesId(productionTaskDetail.getNextProductionProcessesId());
        //将负责人赋值为接收人id
        productionTaskDetail.setPersonLiableId(SecurityUtils.getUserId());
        //清空接收人
        productionTaskDetail.setReceivedUserId(-1l);

        //清空下一工序
        productionTaskDetail.setNextProductionProcessesId(-1l);



        //查找下一工序相关信息 如果有则赋值
        ProductionTask productionTask = productionTaskService.getById(productionTaskDetail.getProductionTaskId());
        ProductionPlan productionPlan = productionPlanService.getById(productionTask.getProductionPlanId());
        WorkOrder workOrder = workOrderService.getById(productionPlan.getWorkOrderId());
        if ("1".equals(workOrder.getIsCustomized())) {
            List<WorkOrderProductionProcesses> workOrderProductionProcesses = workOrderProductionProcessesService.list(q -> q
                    .eq(WorkOrderProductionProcesses::getWorkOrderId, workOrder.getId())
                    .orderByAsc(WorkOrderProductionProcesses::getSort));
            if (ObjectUtil.isEmpty(workOrderProductionProcesses)) {
                throw new ServiceException("定制工单 工序列表为空");
            }

            //赋值下一工序id
            for (int i = 0; i < workOrderProductionProcesses.size(); i++) {
                WorkOrderProductionProcesses wopp = workOrderProductionProcesses.get(i);
                if (wopp.getId().equals(productionTaskDetail.getProductionProcessesId())) {
                    //默认赋值空 如果有下一节点赋值下一节点id
                    if ((i + 1) < workOrderProductionProcesses.size()) {
                        WorkOrderProductionProcesses nextProductionProcesses = workOrderProductionProcesses.get(i + 1);
                        productionTaskDetail.setNextProductionProcessesId(nextProductionProcesses.getId());
                        break;
                    }
                }
            }
        } else {
            ApplicableProducts applicableProducts = applicableProductsService.getOne(q -> q.eq(ApplicableProducts::getProductId, workOrder.getProductId()));
            if (ObjectUtil.isEmpty(applicableProducts)) {
                throw new ServiceException("未找到适用于该产品的工艺信息");
            }
            Technology technology = technologyService.getById(applicableProducts.getTechnologyId());
            if (ObjectUtil.isEmpty(technology)) {
                throw new ServiceException("工艺信息不存在");
            }
            String processRoute = technology.getProcessRoute();
            if (ObjectUtil.isEmpty(processRoute)) {
                throw new ServiceException("工艺线路为空");
            }
            String[] split = processRoute.split(",");
            //赋值下一工序id
            for (int i = 0; i < split.length; i++) {
                if (Long.parseLong(split[i])==productionTaskDetail.getProductionProcessesId()) {
                    //默认赋值空 如果有下一节点赋值下一节点id
                    if ((i + 1) < split.length) {
                        productionTaskDetail.setNextProductionProcessesId(Long.parseLong(split[i + 1]));
                        break;
                    }
                }
            }
        }

        this.updateById(productionTaskDetail);

        //创建任务明细记录
        ProductionTaskDetailRecord productionTaskDetailRecord = new ProductionTaskDetailRecord();
        productionTaskDetailRecord.setProductionTaskDetailId(productionTaskDetail.getId());
        productionTaskDetailRecord.setProductionProcessesId(productionTaskDetail.getProductionProcessesId());
        productionTaskDetailRecord.setPersonLiableId(SecurityUtils.getUserId());
        productionTaskDetailRecordService.save(productionTaskDetailRecord);
    }

    /**
     * 任务接收拒绝
     */
    @Override
    public void rejection(ProductionTaskDetailDto productionTaskDetailDto) {
        //取消流转状态
        productionTaskDetailDto.setCirculationStatus(0);
        //将接收人赋值为空
        productionTaskDetailDto.setReceivedUserId(-1l);
        this.updateById(productionTaskDetailDto);
    }


    @Override
    public ProductionTaskDetailVo snInfo(String sn){
        Assert.notEmpty(sn, "sn不能为空");
        ProductionTaskDetailVo productionTaskDetailVo = baseMapper.snInfo(sn);
        Assert.notEmpty(productionTaskDetailVo, "查询不到sn信息");
        ProductInfo productInfo = productInfoService.getById(productionTaskDetailVo.getProductId());
        Assert.notEmpty(productInfo, "查询不到产品信息");
        productionTaskDetailVo.setProductName(productInfo.getName());
        return productionTaskDetailVo;
    }

}
