package com.njcn.harmonic.service.upload.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.harmonic.mapper.upload.RUploadSubstationStatisticalDataDMapper;
import com.njcn.harmonic.pojo.dto.upload.SubstationQualityStatisticsDTO;
import com.njcn.harmonic.pojo.param.UploadDataParam;
import com.njcn.harmonic.pojo.param.UploadParam;
import com.njcn.harmonic.pojo.po.upload.RUploadPointStatisticalDataD;
import com.njcn.harmonic.pojo.po.upload.RUploadSubstationStatisticalDataD;
import com.njcn.harmonic.pojo.vo.upload.UploadSubstationStatisticalDataVo;
import com.njcn.harmonic.service.upload.ISubstationStatisticalDataService;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.user.pojo.po.Dept;
import com.njcn.web.enums.GWSendEnum;
import com.njcn.web.factory.PageFactory;
import com.njcn.web.pojo.param.SendParam;
import com.njcn.web.utils.GwSendUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 主配网变电站监测统计数据-日表 服务实现类
 * </p>
 *
 * @author xuyang
 * @since 2023-12-08
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class RSubstationStatisticalDataServiceImpl extends ServiceImpl<RUploadSubstationStatisticalDataDMapper, RUploadSubstationStatisticalDataD> implements ISubstationStatisticalDataService {

    private final DeptFeignClient deptFeignClient;
    @Override
    public Page<UploadSubstationStatisticalDataVo> getSubstationStatisticalData(UploadDataParam param) {
        LambdaQueryWrapper<RUploadSubstationStatisticalDataD> lambdaQueryWrapper = getDeptLevel(param);
        //默认按照省名称排序
        lambdaQueryWrapper.orderByDesc(RUploadSubstationStatisticalDataD::getProvinceName);
        Page<RUploadSubstationStatisticalDataD> page = this.page(new Page<>(PageFactory.getPageNum(param), PageFactory.getPageSize(param)), lambdaQueryWrapper);
        List<UploadSubstationStatisticalDataVo> voList = BeanUtil.copyToList(page.getRecords(), UploadSubstationStatisticalDataVo.class);

        Page<UploadSubstationStatisticalDataVo> pageVo = new Page<>();
        pageVo.setTotal(page.getTotal());
        pageVo.setPages(page.getPages());
        pageVo.setSize(page.getSize());
        pageVo.setRecords(voList);
        pageVo.setCurrent(page.getCurrent());
        return pageVo;
    }

    @Override
    public String uploadSubstationStatisticalData(UploadParam param) {

        List<RUploadSubstationStatisticalDataD> list;
        //指定数据上送,不管之前有没有上送,都重新上送一次
        //(预防之前上送过,修改数据后需要再次上送)
        if (CollUtil.isNotEmpty(param.getList())){
            list = this.lambdaQuery()
                    .eq(RUploadSubstationStatisticalDataD::getStatisticalDate,param.getTime())
                    .in(RUploadSubstationStatisticalDataD::getId,param.getList())
                    .list();
        }
        //未指定数据上送,则将所有未上送的数据,上送上去
        else {
            list = this.lambdaQuery()
                    .eq(RUploadSubstationStatisticalDataD::getStatisticalDate,param.getTime())
                    .eq(RUploadSubstationStatisticalDataD::getUploadStatus,0)
                    .eq(RUploadSubstationStatisticalDataD::getCityId,"")
                    .eq(RUploadSubstationStatisticalDataD::getCountyId,"")
                    .list();
        }
        //处理时间
        String[] arr = param.getTime().split("-");
        String time = arr[0]+"-"+arr[1];
        List<SubstationQualityStatisticsDTO> dtoList = BeanUtil.copyToList(list, SubstationQualityStatisticsDTO.class);
        //以尺寸100分片
        List<List<SubstationQualityStatisticsDTO>> pendingIds = ListUtils.partition(dtoList, 100);
        //分片上传
        for (int i = 0; i < pendingIds.size(); i++) {
            SendParam sp = new SendParam();
            sp.setStats(pendingIds.get(i));
            sp.setStatisticalDate(time);
            //上送数据
            Map<String, String> send = GwSendUtil.send(sp, GWSendEnum.SUBSTATION_MONITOR);
            //获取返回结果
            List<String> l = pendingIds.get(i).stream().map(SubstationQualityStatisticsDTO::getId).collect(Collectors.toList());
            returnInformation(i,l,send);
        }
        return "上送成功:成功数据" + list.size() + "条";
    }

    /**
     * 获取当前单位的层级
     */
    public LambdaQueryWrapper<RUploadSubstationStatisticalDataD> getDeptLevel(UploadDataParam param) {
        Dept dept = deptFeignClient.getDeptByCode(param.getOrgId()).getData();
        List<String> list = Arrays.stream(dept.getPids().split(",")).map(String::trim).collect(Collectors.toList());
        LambdaQueryWrapper<RUploadSubstationStatisticalDataD> lambdaQueryWrapper = new LambdaQueryWrapper<>();

        switch (list.size()) {
            //国
            case 1:
                List<Dept> l1 = deptFeignClient.getDirectSonSelf(dept.getId()).getData();
                String orgId = l1.stream().filter(o->!Objects.equals(o.getId(),dept.getId())).findFirst().orElse(null).getCode();
                lambdaQueryWrapper.eq(RUploadSubstationStatisticalDataD::getProvinceId,orgId)
                        .between(RUploadSubstationStatisticalDataD::getStatisticalDate,param.getSearchBeginTime(),param.getSearchEndTime())
                        .eq(!Objects.isNull(param.getSearchState()),RUploadSubstationStatisticalDataD::getUploadStatus,param.getSearchState());
                break;
            //省
            case 2:
                lambdaQueryWrapper.eq(RUploadSubstationStatisticalDataD::getProvinceId,param.getOrgId())
                        .between(RUploadSubstationStatisticalDataD::getStatisticalDate,param.getSearchBeginTime(),param.getSearchEndTime())
                        .eq(!Objects.isNull(param.getSearchState()),RUploadSubstationStatisticalDataD::getUploadStatus,param.getSearchState());
                break;
            //市
            case 3:
                lambdaQueryWrapper.eq(RUploadSubstationStatisticalDataD::getCityId, param.getOrgId())
                        .between(RUploadSubstationStatisticalDataD::getStatisticalDate,param.getSearchBeginTime(),param.getSearchEndTime())
                        .eq(!Objects.isNull(param.getSearchState()),RUploadSubstationStatisticalDataD::getUploadStatus,param.getSearchState());
                break;
            //县
            case 4:
                lambdaQueryWrapper.eq(RUploadSubstationStatisticalDataD::getCountyId, param.getOrgId())
                        .between(RUploadSubstationStatisticalDataD::getStatisticalDate,param.getSearchBeginTime(),param.getSearchEndTime())
                        .eq(!Objects.isNull(param.getSearchState()),RUploadSubstationStatisticalDataD::getUploadStatus,param.getSearchState());
                break;
            default:
                break;
        }
        return lambdaQueryWrapper;
    }

    /**
     * 国网上送返回信息
     *
     * @param step  分片上传当前阶段
     * @param ids   分片数据
     * @param send  上送结果
     * @return
     */
    private void returnInformation(Integer step, List<String> ids, Map<String, String> send) {
        if (send.containsKey("succeed")) {
            String succeed = send.get("succeed");
            if (succeed.contains("\\\"")) {
                succeed = succeed.replace("\\\"", "\"");
            }
            Map mapData = JSON.parseObject(succeed, Map.class);
            String status = mapData.get("status").toString();
            if ("000000".equals(status)) {
                //修改数据上送状态
                updateState(ids);
                String result = mapData.get("result").toString();
                Map mapCount = JSON.parseObject(result, Map.class);
                String count = mapCount.get("count").toString();
            } else {
                String errors = mapData.get("errors").toString();
                int start = step * 100;
                int end = (step+1) * 100;
                throw new BusinessException("上送"+start+"条至"+end+"条数据,上送失败:" + status + "_" + errors);
            }
        } else {
            throw new BusinessException("当前时间段国网上送请求过多，请稍后再试");
        }
    }

    /**
     * 修改上送信息状态
     * @param ids id集合
     */
    private void updateState(List<String> ids) {
        LambdaUpdateWrapper<RUploadSubstationStatisticalDataD> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.in(RUploadSubstationStatisticalDataD::getId, ids)
                .set(RUploadSubstationStatisticalDataD::getUploadStatus, 1);
        this.update(lambdaUpdateWrapper);
    }
}
