package com.fjhx.service.v3.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.constants.DetpIdConstant;
import com.fjhx.constants.StatusConstant;
import com.fjhx.entity.v3.V3Plan;
import com.fjhx.entity.v3.V3PlanStatistics;
import com.fjhx.mapper.v3.V3PlanMapper;
import com.fjhx.params.v3.MaterialMath;
import com.fjhx.params.v3.PlanDataMap;
import com.fjhx.service.v3.V3PlanService;
import com.fjhx.service.v3.V3PlanStatisticsService;
import com.fjhx.service.water.WaterBackService;
import com.fjhx.utils.Assert;
import com.fjhx.utils.GetV3DateUtil;
import org.springblade.system.user.feign.IUserSearchClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2022-10-26
 */
@Service
public class V3PlanServiceImpl extends ServiceImpl<V3PlanMapper, V3Plan> implements V3PlanService {

    @Resource
    private IUserSearchClient userSearchClient;

    @Autowired
    private V3PlanStatisticsService v3PlanStatisticsService;

    @Autowired
    private WaterBackService waterBackService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void statisticsOfFabricUtilizationRate(int offset) {

        Date date = new Date();

        Date beginDate = DateUtil.beginOfDay(DateUtil.offsetDay(date, -offset));
        Date endDate = DateUtil.endOfDay(date);

        // 更新排班数据
        List<V3Plan> v3Plans = renewPlanData(date, beginDate, endDate);

        // 统计面料使用率
        statisticsOfFabricUtilizationRate(v3Plans, date, beginDate, endDate);

    }

    private List<V3Plan> renewPlanData(Date date, Date beginDate, Date endDate) {
        JSONArray planData = GetV3DateUtil.getPlanData(beginDate, endDate);
        remove(Wrappers.<V3Plan>lambdaQuery().between(V3Plan::getPlanDate, beginDate, endDate));

        Map<String, V3Plan> V3PlanMap = new LinkedHashMap<>();
        HashSet<String> jobNoSet = new HashSet<>();

        for (Object planDatum : planData) {
            JSONObject item = (JSONObject) planDatum;

            // 喷印人员工号
            Long distributor = item.getLong("distributor");
            // 打纸人员工号
            Long paperMan = item.getLong("paperMan");
            // 排班面积
            BigDecimal planTotalSquare = item.getBigDecimal("plantotalsquare");
            // 物料名称
            String material = item.getString("material");
            // 排班时间
            Date planDate = item.getDate("planDate");

            // 喷印人员工号添加排班记录
            addOrEditV3PlanMap(V3PlanMap, distributor, planTotalSquare, planDate, material, date, jobNoSet);

            // 打纸人员工号添加排班记录
            addOrEditV3PlanMap(V3PlanMap, paperMan, planTotalSquare, planDate, "热转印纸", date, jobNoSet);

        }

        List<V3Plan> v3PlanList = new ArrayList<>(V3PlanMap.values());
        Map<String, Long> userIdMap = Assert.result(userSearchClient.getUserIdByJobNo(new ArrayList<>(jobNoSet)));

        // 赋值用户排班
        v3PlanList.forEach(item -> item.setUserId(userIdMap.get(item.getJobNo().toString())));

        // 更新排班
        saveBatch(v3PlanList);

        return v3PlanList;
    }

    /**
     * 更新排班数据
     */
    private void addOrEditV3PlanMap(Map<String, V3Plan> flagMap, Long jobNo, BigDecimal planTotalSquare,
                                    Date planDate, String material, Date date, HashSet<String> jobNoSet) {
        if (Objects.equals(jobNo, 0L)) {
            return;
        }

        jobNoSet.add(jobNo.toString());

        String key = jobNo + material + planDate;
        V3Plan v3Plan = flagMap.get(key);

        if (v3Plan == null) {
            v3Plan = new V3Plan();
            v3Plan.setPlanMaterial(material.trim());
            v3Plan.setPlanDate(planDate);
            v3Plan.setArea(planTotalSquare);
            v3Plan.setJobNo(jobNo);
            v3Plan.setCreateTime(date);

            flagMap.put(key, v3Plan);
        } else {
            v3Plan.setArea(v3Plan.getArea().add(planTotalSquare));
        }
    }

    /**
     * 统计面料使用率
     */
    private void statisticsOfFabricUtilizationRate(List<V3Plan> v3PlanList, Date date, Date beginDate, Date endDate) {
        v3PlanStatisticsService.remove(Wrappers.<V3PlanStatistics>lambdaQuery()
                .between(V3PlanStatistics::getPlanDate, beginDate, endDate));

        List<Long> userId = waterBackService.getUserIdByAppointDept(DetpIdConstant.JET_PRINT, DetpIdConstant.TYPING);
        List<Long> transferUserId = waterBackService.getUserIdByAppointDept(DetpIdConstant.TRANSFER);

        // 用户id，物料名称，排班时间封装成key，对象为value
        PlanDataMap planDataMap = new PlanDataMap();
        for (V3Plan v3Plan : v3PlanList) {
            V3PlanStatistics v3PlanStatistics = planDataMap.get(v3Plan.getUserId(),
                    v3Plan.getPlanMaterial(), v3Plan.getPlanDate(), date);
            v3PlanStatistics.setPlanArea(v3Plan.getArea());
        }

        // 出库
        issue(planDataMap, beginDate, userId, date, 7, 30);
        // 转印部门出库
        issue(planDataMap, beginDate, transferUserId, date, 8, 0);
        // 回仓
        back(planDataMap, beginDate, userId, date, 10, 0);
        // 转印部门回仓
        back(planDataMap, beginDate, transferUserId, date, 10, 0);
        // 转入
        in(planDataMap, beginDate, transferUserId, date, 0, 0);
        // 转出
        out(planDataMap, beginDate, transferUserId, date, 10, 0);

    }

    /**
     * 出库
     */
    private void issue(PlanDataMap planDataMap, Date beginDate, List<Long> userId, Date date, int h, int m) {

        List<MaterialMath> list = baseMapper.issue(Wrappers.query()
                .ge("wd.create_time", DateUtil.format(beginDate, String.format("yyyy-MM-dd %s:%s:00", h, m)))
                .in("wd.oper_user_id", userId)
                .in("wd.type", 20, 23)
                .likeRight("m.code", "01."));

        for (MaterialMath materialMath : list) {
            V3PlanStatistics v3PlanStatistics = planDataMap.get(materialMath.getUserId(),
                    materialMath.getMaterialName(), materialMath.getCreateTime(h, m), date);
            // 金额
            v3PlanStatistics.setPickingMoney(v3PlanStatistics.getPickingMoney().add(materialMath.getMoney()));
            // 数量
            v3PlanStatistics.setPickingNum(v3PlanStatistics.getPickingNum() + 1);
            // 米
            v3PlanStatistics.setPickingMeters(v3PlanStatistics.getPickingMeters().add(materialMath.getQuantity()));
            // 面积
            v3PlanStatistics.setPickingArea(v3PlanStatistics.getPickingArea().add(materialMath.getArea()));
        }
    }

    /**
     * 回仓
     */
    private void back(PlanDataMap planDataMap, Date beginDate, List<Long> userId, Date date, int h, int m) {

        List<MaterialMath> list = baseMapper.back(Wrappers.query()
                .ge("wbd.create_time", DateUtil.format(beginDate, String.format("yyyy-MM-dd %s:%s:00", h, m)))
                .in("wbd.create_user", userId)
                .in("wbd.del_flag", StatusConstant.NOT_DELETED)
                .likeRight("m.code", "01."));

        for (MaterialMath materialMath : list) {
            V3PlanStatistics v3PlanStatistics = planDataMap.get(materialMath.getUserId(),
                    materialMath.getMaterialName(), materialMath.getCreateTime(h, m), date);
            // 金额
            v3PlanStatistics.setBackMoney(v3PlanStatistics.getBackMoney().add(materialMath.getMoney()));
            // 数量
            v3PlanStatistics.setBackNum(v3PlanStatistics.getBackNum() + 1);
            // 米
            v3PlanStatistics.setBackMeters(v3PlanStatistics.getBackMeters().add(materialMath.getQuantity()));
            // 面积
            v3PlanStatistics.setBackArea(v3PlanStatistics.getBackArea().add(materialMath.getArea()));
        }
    }

    /**
     * 转入
     */
    private void in(PlanDataMap planDataMap, Date beginDate, List<Long> userId, Date date, int h, int m) {

        List<MaterialMath> list = baseMapper.in(Wrappers.query()
                .ge("wtd.create_time", DateUtil.format(beginDate, String.format("yyyy-MM-dd %s:%s:00", h, m)))
                .in("wtd.receive_id", userId)
                .likeRight("m.code", "01."));

        for (MaterialMath materialMath : list) {
            V3PlanStatistics v3PlanStatistics = planDataMap.get(materialMath.getUserId(),
                    materialMath.getMaterialName(), materialMath.getCreateTime(h, m), date);
            // 金额
            v3PlanStatistics.setTransferInMoney(v3PlanStatistics.getTransferInMoney().add(materialMath.getMoney()));
            // 数量
            v3PlanStatistics.setTransferInNum(v3PlanStatistics.getTransferInNum() + 1);
            // 米
            v3PlanStatistics.setTransferInMeters(v3PlanStatistics.getTransferInMeters().add(materialMath.getQuantity()));
            // 面积
            v3PlanStatistics.setTransferInArea(v3PlanStatistics.getTransferInArea().add(materialMath.getArea()));
        }
    }

    /**
     * 转入
     */
    private void out(PlanDataMap planDataMap, Date beginDate, List<Long> userId, Date date, int h, int m) {

        List<MaterialMath> list = baseMapper.out(Wrappers.query()
                .ge("wtd.create_time", DateUtil.format(beginDate, String.format("yyyy-MM-dd %s:%s:00", h, m)))
                .in("wtd.create_user", userId)
                .likeRight("m.code", "01."));

        for (MaterialMath materialMath : list) {
            V3PlanStatistics v3PlanStatistics = planDataMap.get(materialMath.getUserId(),
                    materialMath.getMaterialName(), materialMath.getCreateTime(h, m), date);
            // 金额
            v3PlanStatistics.setTransferOutMoney(v3PlanStatistics.getTransferOutMoney().add(materialMath.getMoney()));
            // 数量
            v3PlanStatistics.setTransferOutNum(v3PlanStatistics.getTransferOutNum() + 1);
            // 米
            v3PlanStatistics.setTransferOutMeters(v3PlanStatistics.getTransferOutMeters().add(materialMath.getQuantity()));
            // 面积
            v3PlanStatistics.setTransferOutArea(v3PlanStatistics.getTransferOutArea().add(materialMath.getArea()));
        }
    }

}
