/*
 * Author: Zev
 * 生成ServiceImpl
 */
package com.tofly.gpsboot.service.process.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.tofly.api.UserTaskClient;
import com.tofly.common.oauth.util.SecurityUtils;
import com.tofly.gpsboot.common.Constant;
import com.tofly.gpsboot.common.system.IsPlaceEnum;
import com.tofly.gpsboot.common.system.MessageTopicEnum;
import com.tofly.gpsboot.common.system.PlanStateEnum;
import com.tofly.gpsboot.common.system.UserTaskStateEnumEnum;
import com.tofly.gpsboot.service.paln.PlanchildtypeService;
import com.tofly.gpsboot.service.paln.PlantypeService;
import com.tofly.gpsboot.util.DateTimeUtil;
import com.tofly.pojo.message.Usertask;
import com.tofly.pojo.plan.*;
import com.tofly.pojo.plan.dto.PointtempDto;
import com.tofly.pojo.plan.vo.PointtempVo;
import com.tofly.gpsboot.mapper.plan.PointtempMapper;
import com.tofly.gpsboot.service.paln.task.PlanService;
import com.tofly.gpsboot.service.paln.task.PlanchildService;
import com.tofly.gpsboot.service.process.PointtempService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;


/**
 * 巡检计划点到位信息表：TF_YWPN_POINTTEMP_W
 *
 * @author admin
 * @date Thu Mar 18 00:00:00 CST 2021
 */
@Service("pointtempService")
@Slf4j
public class PointtempServiceImpl extends ServiceImpl<PointtempMapper, Pointtemp> implements PointtempService {

    @Autowired
    private PlanService planService;

    @Autowired
    private PlanchildService planchildService;
    @Autowired
    private UserTaskClient userTaskClient;
    @Autowired
    private PlantypeService plantypeService;
    @Autowired
    private PlanchildtypeService planchildtypeService;

    @Override
    public List<PointtempVo> viewConversion(List<Pointtemp> infoList) {
        List<PointtempVo> infoVoList = new ArrayList<>();
        infoList.forEach(info -> {
            PointtempVo baseInfo = JSONObject.parseObject(JSONObject.toJSONString(info), PointtempVo.class);
            // 转换是否到位
            baseInfo.setIsoverName(IsPlaceEnum.getCodeForValue(info.getIsover()));
            infoVoList.add(baseInfo);
        });
        return infoVoList;
    }

    @Override
    public Page<PointtempVo> getInfoPage(Page page, PointtempDto parDto) {

        Pointtemp pointtemp = JSONObject.parseObject(JSON.toJSONString(parDto), Pointtemp.class);
        QueryWrapper<Pointtemp> wrapper = new QueryWrapper();

        if (!StringUtils.isEmpty(parDto.getStartTime()) && !StringUtils.isEmpty(parDto.getEndTime())) {
            wrapper.ge("CREATE_TIME", parDto.getStartTime());
            wrapper.le("CREATE_TIME", parDto.getEndTime());
            pointtemp.setCreateTime(null);
        }

        wrapper.setEntity(pointtemp);
        Page infoPageList = this.page(page, wrapper);
        infoPageList.setRecords(this.viewConversion(infoPageList.getRecords()));
        return infoPageList;
    }


    public Boolean updatePointTempList_Old(List<Pointtemp> pointtemps) {
        // 相关巡检完成率计算
        // 获取当前用户Id
        Long userid = SecurityUtils.getUser().getUserid();
        // 根据传入参数 点id 获取对应点列表
        List<Pointtemp> pointTempList = this.listByIds(pointtemps.stream().map(Pointtemp::getId).collect(Collectors.toList()));
        // 赋值点到为状态为1 更新当前时间
        pointTempList.forEach(f -> {
            f.setIsover(IsPlaceEnum.IS_PLACE_NO.getCode());
            f.setOverDate(new Date());
        });
        // 传入参数 按照计划ID分组
        Map<Long, List<Pointtemp>> collect = pointTempList.stream().collect(Collectors.groupingBy(Pointtemp::getPlanId, Collectors.toList()));

        // 区分巡检和养护(养护直接不参与计算完成率计算,只修改点到位)
        List<Plan> planList = planService.listByIds(collect.keySet());
        List<Plan> inspectPlanList = planList.stream().filter(i -> !"1".equals(i.getMaintenanceFlag())).collect(Collectors.toList());
        // 主计划数据源 按照计划id分组
        Map<Long, Plan> planMap = inspectPlanList.stream().collect(Collectors.toMap(Plan::getId, a -> a, (k1, k2) -> k1));

        // 子计划数据源 按照计划id分组(由于根据用户查询,计划中的子计划只能有一个)
        Map<Long, Planchild> planChildMap = planchildService.list(new QueryWrapper<Planchild>().lambda().eq(Planchild::getRespUser, userid).in(Planchild::getPlanId, planMap.keySet())).stream().collect(Collectors.toMap(Planchild::getPlanId, a -> a, (k1, k2) -> k1));

        // 保存更新后的对应计划统计完成对象
        Map<Long, List<Plantype>> overPlanTypeMap = new HashMap<>(12);
        // 更新计划类型完成
        collect.forEach((k, v) -> {
            // 子计划
            Planchild planchild = planChildMap.get(k);
            if(planchild!=null) {
                Map<Long, Long> collect1 = v.stream().collect(Collectors.groupingBy(Pointtemp::getInspectTypeId, Collectors.counting()));
                Map<Long, DoubleSummaryStatistics> collect2 = v.stream().filter(i -> null != i.getPipeLength()).collect(Collectors.groupingBy(Pointtemp::getInspectTypeId, Collectors.summarizingDouble(p -> p.getPipeLength().doubleValue())));
                collect1.forEach((m, n) -> {
                    Plantype one = plantypeService.getOne(new QueryWrapper<Plantype>().lambda().eq(Plantype::getPlanId, k)
                            .eq(Plantype::getTypeId, m));
                    if (null != one) {
                        BigDecimal overCount = one.getOverCount();
                        BigDecimal overLength = one.getOverLength();
                        BigDecimal totalCount = one.getTotalCount();
                        BigDecimal totalLength = one.getTotalLength();
                        BigDecimal length = (overLength == null ? BigDecimal.ZERO : overLength).add(BigDecimal.valueOf(null == collect2.get(m) ? 0 : collect2.get(m).getSum()));
                        BigDecimal overNum = (overCount == null ? BigDecimal.ZERO : overCount).add(BigDecimal.valueOf(n));
                        if(overNum.compareTo(totalCount)>=0){
                            overNum=totalCount;

                        }
                        BigDecimal multiply = overNum.multiply(BigDecimal.valueOf(100)).divide(totalCount, 2, BigDecimal.ROUND_HALF_UP);
                        one.setOverCount(overNum);
                        if(length.compareTo(totalLength)>=0){
                            length=totalLength;

                        }
                        one.setOverLength(length);
                        one.setPercent(multiply.floatValue());
                        plantypeService.updateById(one);
                        List<Plantype> plantypeList = overPlanTypeMap.get(k);
                        if (null != plantypeList && plantypeList.size() > 0) {
                            plantypeList.add(one);
                            overPlanTypeMap.put(k, plantypeList);
                        } else {
                            List<Plantype> plantypeList1 = new ArrayList<>();
                            plantypeList1.add(one);
                            overPlanTypeMap.put(k, plantypeList1);
                        }

                        // 个人完成率
                        List<Planchildtype> list = planchildtypeService.list(new QueryWrapper<Planchildtype>().lambda()
                                .eq(Planchildtype::getTypeId, m)
                                .eq(Planchildtype::getPlanChildId, planchild.getId())
                                .eq(Planchildtype::getUserId, planchild.getRespUser()));
                        Planchildtype planchildtype = new Planchildtype();
                        if (null != list && list.size() > 0) {
                            Planchildtype child = list.get(0);
                            planchildtype.setId(child.getId());
                            BigDecimal overCount_1= child.getOverCount().add(BigDecimal.valueOf(n));

                            if(overCount_1.compareTo(totalCount)>=0){
                                overCount_1=totalCount;

                            }
                            planchildtype.setOverCount(overCount_1);
                            BigDecimal overLength_1=child.getOverLength().add(BigDecimal.valueOf(null == collect2.get(m) ? 0 : collect2.get(m).getSum()));

                            if(overLength_1.compareTo(length)>=0){
                                overLength_1=length;

                            }
                            planchildtype.setOverLength(overLength_1);

                            planchildtype.setPercent(planchildtype.getOverCount().divide(totalCount, 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).floatValue());
                        } else {
                            planchildtype.setOverCount(overNum);
                            planchildtype.setOverLength(length);
                            planchildtype.setPercent(multiply.floatValue());
                        }
                        planchildtype.setPlanChildId(planchild.getId());
                        planchildtype.setUserId(planchild.getRespUser());
                        planchildtype.setTotalCount(totalCount);
                        planchildtype.setTotalLength(totalLength);
                        planchildtype.setCompletionRate(one.getCompletionRate());
                        planchildtype.setTypeId(one.getTypeId());
                        planchildtypeService.saveOrUpdate(planchildtype);
                    }
                });
            }
        });
        // 判断当前计划对应的类型计划是否达到对应的计划完成率

        planMap.forEach((k, v) -> {
            List<Plantype> planTypeList = overPlanTypeMap.get(k);
            if(null!=planTypeList && planTypeList.size()>0){
                int size = planTypeList.size();
                AtomicInteger overNum = new AtomicInteger();
                planTypeList.forEach(planType -> {
                    Float completionRate = planType.getCompletionRate();
                    Float percent = planType.getPercent();
                    if (completionRate<=percent) {
                        overNum.set(overNum.get() + 1);
                    }
                });
                if (size == overNum.get()) {
                    v.setPlanState(PlanStateEnum.PLAN_STATE_PLAN_COMPLETE.getCode());
                    // 待办事项处理
                    Usertask usertask = new Usertask();
                    usertask.setTableName(MessageTopicEnum.TASK_PLAN_SEND.getTableName());
                    usertask.setTableId(k);
                    List<Usertask> result = userTaskClient.getUserTaskInfo(usertask).getResult();
                    if (null != result && result.size() > 0) {
                        result.forEach(task -> {
                            task.setHandleTime(DateTimeUtil.convertLDTToDate(LocalDateTime.now()));
                            task.setIshandle(UserTaskStateEnumEnum.IS_HANDLER_COMPLETED.getCode());
                            userTaskClient.updateById(task);
                        });

                    }
                }
            }


        });


        // 更新计划及子计划
        planService.updateBatchById(planMap.values());
        planchildService.updateBatchById(planChildMap.values());
        return this.updateBatchById(pointTempList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updatePointTempList(List<Pointtemp> pointtemps) {
        // 相关巡检完成率计算
        // 获取当前用户Id
        Long userid = SecurityUtils.getUser().getUserid();
        // 根据传入参数 点id 获取对应点列表
        List<Pointtemp> pointTempList = this.listByIds(pointtemps.stream().map(Pointtemp::getId).collect(Collectors.toList()));
        // 赋值点到为状态为1 更新当前时间

        pointTempList.forEach(f -> {
            f.setIsover(IsPlaceEnum.IS_PLACE_NO.getCode());
            f.setOverDate(new Date());
            f.setUserId(SecurityUtils.getUserId());
        });
        // 传入参数 按照计划ID分组
        Map<Long, List<Pointtemp>> collect = pointTempList.stream().collect(Collectors.groupingBy(Pointtemp::getPlanId, Collectors.toList()));

        // 主计划数据源 按照计划id分组
        Map<Long, Plan> planMap = planService.listByIds(collect.keySet()).stream().collect(Collectors.toMap(Plan::getId, a -> a, (k1, k2) -> k1));
        // 子计划数据源 按照计划id分组(由于根据用户查询,计划中的子计划只能有一个)
        Map<Long, Planchild> planChildMap = planchildService.list(new QueryWrapper<Planchild>().lambda().eq(Planchild::getRespUser, userid).in(Planchild::getPlanId, planMap.keySet())).stream().collect(Collectors.toMap(Planchild::getPlanId, a -> a, (k1, k2) -> k1));


        // 保存更新后的对应计划统计完成对象
        Map<Long, Plantype> overPlanTypeMap = new HashMap<>(12);
        // 更新计划类型完成
        collect.forEach((k, v) -> {
            // 子计划
            Planchild planchild = planChildMap.get(k);
            Map<Long, Long> collect1 = v.stream().collect(Collectors.groupingBy(Pointtemp::getInspectTypeId, Collectors.counting()));
            Map<Long, DoubleSummaryStatistics> collect2 = v.stream().filter(i -> null != i.getPipeLength()).collect(Collectors.groupingBy(Pointtemp::getInspectTypeId, Collectors.summarizingDouble(p -> p.getPipeLength().doubleValue())));
            collect1.forEach((m, n) -> {
                Plantype one = plantypeService.getOne(new QueryWrapper<Plantype>().lambda().eq(Plantype::getPlanId, k)
                        .eq(Plantype::getTypeId, m));
                if (null != one) {
                    BigDecimal overCount = one.getOverCount();
                    BigDecimal overLength = one.getOverLength();
                    BigDecimal totalCount = one.getTotalCount()==null?BigDecimal.ZERO :one.getTotalCount();
                    BigDecimal totalLength = one.getTotalLength()==null?BigDecimal.ZERO :one.getTotalLength();
                    BigDecimal length = (overLength == null ? BigDecimal.ZERO : overLength).add(BigDecimal.valueOf(null == collect2.get(m) ? 0 : collect2.get(m).getSum()));
                    BigDecimal overNum = (overCount == null ? BigDecimal.ZERO : overCount).add(BigDecimal.valueOf(n));
                    if(overNum.compareTo(totalCount)>=0){
                        overNum=totalCount;

                    }
                    BigDecimal multiply = overNum.multiply(BigDecimal.valueOf(100)).divide(totalCount, 2, BigDecimal.ROUND_HALF_UP);
                    one.setOverCount(overNum);
                    if(length.compareTo(totalLength)>=0){
                        length=totalLength;

                    }
                    one.setOverLength(length);
                    one.setPercent(multiply.floatValue());
                    plantypeService.updateById(one);
                    overPlanTypeMap.put(k, one);
                    // 个人完成率
                    List<Planchildtype> list = planchildtypeService.list(new QueryWrapper<Planchildtype>().lambda()
                            .eq(Planchildtype::getPlanChildId, planchild.getId())
                            .eq(Planchildtype::getUserId, planchild.getRespUser()));
                    Planchildtype planchildtype = new Planchildtype();
                    if (null != list && list.size() > 0) {
                        Planchildtype child = list.get(0);
                        planchildtype.setId(child.getId());

                       BigDecimal overCountChild=child.getOverCount()==null?BigDecimal.ZERO:child.getOverCount();
                        BigDecimal overCount_1= overCountChild.add(BigDecimal.valueOf(n));

                        if(overCount_1.compareTo(totalCount)>=0){
                            overCount_1=totalCount;

                        }
                        planchildtype.setOverCount(overCount_1);
                        BigDecimal overLength_1=(child.getOverLength()==null?BigDecimal.ZERO:child.getOverLength()).add(BigDecimal.valueOf(null == collect2.get(m) ? 0 : collect2.get(m).getSum()));

                        if(overLength_1.compareTo(length)>=0){
                            overLength_1=length;

                        }
                        planchildtype.setOverLength(overLength_1);

                        planchildtype.setPercent(planchildtype.getOverCount().multiply(BigDecimal.valueOf(100).divide(totalCount, 2, BigDecimal.ROUND_HALF_UP)).floatValue());
                    } else {
                        planchildtype.setOverCount(overNum);
                        planchildtype.setOverLength(length);
                        planchildtype.setPercent(multiply.floatValue());
                    }
                    planchildtype.setPlanChildId(planchild.getId());
                    planchildtype.setUserId(planchild.getRespUser());
                    planchildtype.setTotalCount(totalCount);
                    planchildtype.setTotalLength(totalLength);
                    planchildtype.setCompletionRate(one.getCompletionRate());
                    planchildtype.setTypeId(one.getTypeId());
                    planchildtypeService.saveOrUpdate(planchildtype);
                    if (multiply.compareTo(BigDecimal.valueOf(one.getCompletionRate())) == 0) {
                        planchild.setPlanState(PlanStateEnum.PLAN_STATE_PLAN_COMPLETE.getCode());
                        planChildMap.put(k,planchild);
                    }
                }
            });

        });
        // 判断当前计划对应的类型计划是否达到对应的计划完成率
        planMap.forEach((k, v) -> {
            Plantype type = overPlanTypeMap.get(k);
            Float completionRate = type.getCompletionRate();
            Float percent = type.getPercent();
            if (completionRate.equals(percent)) {
                v.setPlanState(PlanStateEnum.PLAN_STATE_PLAN_COMPLETE.getCode());
                // 待办事项处理
                Usertask usertask = new Usertask();
                usertask.setTableName(MessageTopicEnum.TASK_CONSTRUCTION_SITE_SEND.getTableName());
                usertask.setTableId(k);
                List<Usertask> result = userTaskClient.getUserTaskInfo(usertask).getResult();
                if (null != result && result.size() > 0) {
                    result.forEach(task -> {
                        task.setHandleTime(DateTimeUtil.convertLDTToDate(LocalDateTime.now()));
                        task.setIshandle(UserTaskStateEnumEnum.IS_HANDLER_COMPLETED.getCode());
                        userTaskClient.updateById(task);
                    });

                }
            }

        });


        // 更新计划及子计划
        planService.updateBatchById(planMap.values());
        planchildService.updateBatchById(planChildMap.values());
        return this.updateBatchById(pointTempList);
    }

}
