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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
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.production.dto.ProductionReportingDto;
import com.fjhx.mes.entity.production.dto.ProductionReportingSelectDto;
import com.fjhx.mes.entity.production.po.*;
import com.fjhx.mes.entity.production.vo.ProductionReportingDetailVo;
import com.fjhx.mes.entity.production.vo.ProductionReportingVo;
import com.fjhx.mes.entity.technology.po.TechnologyProcessLine;
import com.fjhx.mes.mapper.production.ProductionReportingMapper;
import com.fjhx.mes.service.production.*;
import com.fjhx.mes.service.technology.TechnologyProcessLineService;
import com.ruoyi.common.core.domain.BasePo;
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 org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 * 生产报工 服务实现类
 * </p>
 *
 * @author
 * @since 2023-03-30
 */
@Service
public class ProductionReportingServiceImpl extends ServiceImpl<ProductionReportingMapper, ProductionReporting> implements ProductionReportingService {
    @Autowired
    ProductionReportingDetailService productionReportingDetailService;
    @Autowired
    ProductInfoService productInfoService;
    @Autowired
    ProductionProcessesService productionProcessesService;
    @Autowired
    ProductionTaskService productionTaskService;
    @Autowired
    private ProductionTaskProgressService productionTaskProgressService;
    @Autowired
    private ProduceOrderDetailService produceOrderDetailService;
    @Autowired
    private TechnologyProcessLineService technologyProcessLineService;
    @Autowired
    private ProduceOrderService produceOrderService;


    @Override
    public Page<ProductionReportingVo> getPage(ProductionReportingSelectDto dto) {
        IWrapper<ProductionReporting> wrapper = getWrapper();
        wrapper.orderByDesc("pr", ProductionReporting::getId);
        wrapper.like("pt.code", dto.getKeyword());
        Page<ProductionReportingVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<ProductionReportingVo> records = page.getRecords();
        UserUtil.assignmentNickName(records, ProductionReporting::getCreateUser, ProductionReportingVo::setOperatorName);
        return page;
    }

    @Override
    public ProductionReportingVo detail(Long id) {
        ProductionReportingVo productionReporting = baseMapper.detail(id);
        ProductInfo productInfo = productInfoService.getById(productionReporting.getProductId());
        if (ObjectUtil.isNotEmpty(productInfo)) {
            productionReporting.setProductName(productInfo.getName());
        }
        Map<Long, String> nickNameMapByIds = UserUtil.getNickNameMapByIds(Arrays.asList(productionReporting.getPersonLiableId()));
        if (ObjectUtil.isNotEmpty(nickNameMapByIds)) {
            String name = nickNameMapByIds.get(productionReporting.getPersonLiableId());
            productionReporting.setPersonLiableName(name);
        }

        //赋值报工明细
        List<ProductionReportingDetail> productionReportingDetailList = productionReportingDetailService.list(q -> q.eq(ProductionReportingDetail::getProductionReportingId, productionReporting.getId()));
        List<ProductionReportingDetailVo> productionReportingDetailVos = BeanUtil.copyToList(productionReportingDetailList, ProductionReportingDetailVo.class);
        //赋值工序名称
        List<Long> ProductionProcessesIds = productionReportingDetailList.stream().map(ProductionReportingDetail::getProductionProcessesId).collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(ProductionProcessesIds)) {
            List<ProductionProcesses> productionProcessesList = productionProcessesService.listByIds(ProductionProcessesIds);
            Map<Long, ProductionProcesses> productionProcessesMap = productionProcessesList.stream().collect(Collectors.groupingBy(ProductionProcesses::getId,
                    Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0))));
            for (ProductionReportingDetailVo productionReportingDetailVo : productionReportingDetailVos) {
                Long productionProcessesId = productionReportingDetailVo.getProductionProcessesId();
                ProductionProcesses productionProcesses = productionProcessesMap.get(productionProcessesId);
                if (ObjectUtil.isNotEmpty(productionProcesses)) {
                    productionReportingDetailVo.setProcessesName(productionProcesses.getName());
                }
            }
            productionReporting.setProductionReportingDetailVoList(productionReportingDetailVos);
        }
        return productionReporting;
    }

    @DSTransactional
    @Override
    public synchronized void add(ProductionReportingDto dto) {
        Long productionTaskId = dto.getProductionTaskId();
        Long productionProcessesId = dto.getProductionProcessesId();
        BigDecimal reportingQuantity = dto.getQuantity();
        String userSet = dto.getUserSet();

        Assert.notEmpty(userSet, "报工人不能为空");
        Assert.notEmpty(productionTaskId, "生产任务id不能为空！");
        Assert.notEmpty(productionProcessesId, "生产工序id不能为空！");
        Assert.notEmpty(reportingQuantity, "报工数量不能为空！");

        //赋值归属公司
        Long companyId = SecurityUtils.getCompanyId();
        dto.setCompanyId(companyId);

        //保存报工
        this.save(dto);

        //生成报工明细
        long[] userIdList = Arrays.asList(userSet.split(",")).stream().mapToLong(Long::parseLong).toArray();
        //报工数量所有人平分
        BigDecimal divide = reportingQuantity.divide(BigDecimal.valueOf(userIdList.length), 4, RoundingMode.HALF_UP);
        List<ProductionReportingDetail> productionReportingDetailList = new ArrayList<>();
        for (long userId : userIdList) {
            ProductionReportingDetail productionReportingDetail = new ProductionReportingDetail();
            productionReportingDetail.setProductionReportingId(dto.getId());
            productionReportingDetail.setProductionTaskId(productionTaskId);
            productionReportingDetail.setProductionProcessesId(productionProcessesId);
            productionReportingDetail.setQuantity(divide);
            productionReportingDetail.setUserId(userId);
            productionReportingDetail.setCompanyId(companyId);
            productionReportingDetailList.add(productionReportingDetail);
        }
        productionReportingDetailService.saveBatch(productionReportingDetailList);

        ProductionTaskProgress productionTaskProgress = productionTaskProgressService.getOne(q -> q
                .eq(ProductionTaskProgress::getTaskId, productionTaskId)
                .eq(ProductionTaskProgress::getProcessesId, productionProcessesId)
        );

        Assert.notEmpty(productionTaskProgress, "查询不到生产进度信息");

        Date newDateTime = new Date();

        //更新生产进度信息
        productionTaskProgressService.update(q -> q
                .eq(ProductionTaskProgress::getTaskId, productionTaskId)
                .eq(ProductionTaskProgress::getProcessesId, productionProcessesId)
                .setSql("finish_quantity = finish_quantity + " + dto.getQuantity())
                .set(BasePo::getUpdateTime, newDateTime)
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );

        //更新完工数量
        ProductionOrderDetail productionOrderDetail = produceOrderDetailService.getById(productionTaskId);
        Assert.notEmpty(productionOrderDetail, "查询不到生产任务信息！");
        ProductInfo productInfo = productInfoService.getById(productionOrderDetail.getProductId());
        Assert.notEmpty(productInfo, "查询不到生产产品信息！");
        Long technologyId = productInfo.getTechnologyId();
        //判断报工工序是不是最后一道工序,是增加完工数量
        long count = technologyProcessLineService.count(q -> q
                .eq(TechnologyProcessLine::getTechnologyId, technologyId)
                .eq(TechnologyProcessLine::getSourceProcessesId, productionProcessesId)
                .eq(TechnologyProcessLine::getTargetProcessesId, 99)
        );
        if (count > 0) {
            //是最后一道工序添加完工数量
            BigDecimal quantity = productionOrderDetail.getQuantity();
            BigDecimal finishQuantity = productionOrderDetail.getFinishQuantity();
            //计算完工数量
            BigDecimal add = finishQuantity.add(reportingQuantity);
            productionOrderDetail.setFinishQuantity(add);
            //全部完成赋值完工时间
            if (add.compareTo(quantity) >= 0) {
                productionOrderDetail.setFinishTime(newDateTime);
                productionOrderDetail.setProduceStatus(2);
            }
            produceOrderDetailService.updateById(productionOrderDetail);
        }
        //检查订单下的任务是否完成，更改状态
        Long produceOrderId = productionOrderDetail.getProduceOrderId();
        long count1 = produceOrderDetailService.count(q -> q
                .eq(ProductionOrderDetail::getProduceOrderId, produceOrderId)
                .ne(ProductionOrderDetail::getProduceStatus, 2)
        );
        if (count1 == 0) {
            produceOrderService.update(q -> q
                    .eq(BasePo::getId, produceOrderId)
                    .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
                    .set(BasePo::getUpdateTime, newDateTime)
                    .set(ProductionOrder::getProduceStatus, 2)
                    .set(ProductionOrder::getFinishTime, newDateTime)
            );
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(ProductionReportingDto productionReportingDto) {
//        this.updateById(productionReportingDto);
//        //保存报工明细
//        List<ProductionReportingDetail> productionReportingDetailList = productionReportingDto.getProductionReportingDetailList();
//        for (ProductionReportingDetail productionReportingDetail : productionReportingDetailList) {
//            productionReportingDetail.setProductionReportingId(productionReportingDto.getId());
//        }
//        productionReportingDetailService.updateBatchById(productionReportingDetailList);
    }

    @Override
    public void delete(Long id) {
        this.removeById(id);
        productionReportingDetailService.remove(q -> q.eq(ProductionReportingDetail::getProductionReportingId, id));
    }

}
