package org.jeecg.modules.newWarning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.cas.entity.ENT_USER;
import org.jeecg.modules.cas.entity.WellboreUser;
import org.jeecg.modules.cas.service.IWellboreAuthQuery;
import org.jeecg.modules.dataVue.entity.Ajh;
import org.jeecg.modules.dataVue.service.IAjhService;
import org.jeecg.modules.newWarning.dto.AggregatedResultDto;
import org.jeecg.modules.newWarning.dto.WarnLogComprehensiveDto;
import org.jeecg.modules.newWarning.dto.WarnLogStatisticsDto;
import org.jeecg.modules.newWarning.entity.*;
import org.jeecg.modules.newWarning.mapper.HookLoadWarnLogMapper;
import org.jeecg.modules.newWarning.mapper.PumpingPressureWarnLogMapper;
import org.jeecg.modules.newWarning.mapper.TorqueWarnLogMapper;
import org.jeecg.modules.newWarning.mapper.TotalPoolVolumeWarnLogMapper;
import org.jeecg.modules.newWarning.params.WarnLogCountParams;
import org.jeecg.modules.newWarning.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Zhao RenJi
 * 预警日志查询服务层
 */
@Slf4j
@Service
public class WarnLogServiceImpl implements WarnLogService {

    @Resource
    private HookLoadWarnLogService hookLoadWarnLogService;

    @Resource
    private TorqueWarnLogService torqueWarnLogService;

    @Resource
    private PumpingPressureWarnLogService pumpingPressureWarnLogService;

    @Resource
    private TotalPoolVolumeWarnLogService totalPoolVolumeWarnLogService;

    @Resource
    private WarnOperateLogService warnOperateLogService;

    @Autowired
    IWellboreAuthQuery iWellboreAuthQuery;

    @Autowired
    IAjhService ajhService;

    @Override
    public List<WarnLogComprehensiveDto> getWarnLogListByType(HashMap<String, Object> params) {
        List<WarnLogComprehensiveDto> res = new ArrayList<>();
        String jhs = (String) params.get("jhs");
        List<String> jhList = new ArrayList<>();
        if (!"".equals(jhs)) {
            String[] split = jhs.split(",");
            jhList.addAll(Arrays.asList(split));
        }
        params.put("jhs", jhList);
        String type = (String) params.get("type");
        List<WarnLogComprehensiveDto> hookLoadWarnLogList = new ArrayList<>();
        List<WarnLogComprehensiveDto> torqueWarnLogList = new ArrayList<>();
        List<WarnLogComprehensiveDto> pumpingPressureWarnLogList = new ArrayList<>();
        List<WarnLogComprehensiveDto> totalPoolVolumeWarnLogList = new ArrayList<>();
        switch (type) {
            case "0":
                //综合查询
                hookLoadWarnLogList = hookLoadWarnLogService.getWarnLogList(params);
                torqueWarnLogList = torqueWarnLogService.getWarnLogList(params);
                pumpingPressureWarnLogList = pumpingPressureWarnLogService.getWarnLogList(params);
                totalPoolVolumeWarnLogList = totalPoolVolumeWarnLogService.getWarnLogList(params);
                res.addAll(hookLoadWarnLogList);
                res.addAll(torqueWarnLogList);
                res.addAll(pumpingPressureWarnLogList);
                res.addAll(totalPoolVolumeWarnLogList);
                break;
            case "1":
                //钩载
                hookLoadWarnLogList = hookLoadWarnLogService.getWarnLogList(params);
                res.addAll(hookLoadWarnLogList);
                break;
            case "2":
                //扭矩
                torqueWarnLogList = torqueWarnLogService.getWarnLogList(params);
                res.addAll(torqueWarnLogList);
                break;
            case "3":
                //泵压
                pumpingPressureWarnLogList = pumpingPressureWarnLogService.getWarnLogList(params);
                res.addAll(pumpingPressureWarnLogList);
                break;
            case "4":
                //总池体积
                totalPoolVolumeWarnLogList = totalPoolVolumeWarnLogService.getWarnLogList(params);
                res.addAll(totalPoolVolumeWarnLogList);
                break;
            default:
                break;
        }
        return res;
    }

    @Override
    public Result<?> getWarnLogPageByType(Integer pageNo, Integer pageSize, String type, String jh) {
        Result<?> res = new Result<>();
        switch (type) {
            case "钩载预警":
                //钩载
                Page<HookLoadWarnLog> pageHookLoad = new Page<HookLoadWarnLog>(pageNo, pageSize);
                QueryWrapper<HookLoadWarnLog> wrapperHookLoad = new QueryWrapper<>();
                wrapperHookLoad.lambda().eq(HookLoadWarnLog::getJh, jh).orderByDesc(HookLoadWarnLog::getWarnTime, HookLoadWarnLog::getMobilDrillingToolsStartTime);
                Page<HookLoadWarnLog> hookLoadWarnLogPage = hookLoadWarnLogService.page(pageHookLoad, wrapperHookLoad);
                res = Result.OK(hookLoadWarnLogPage);
                break;
            case "扭矩预警":
                //扭矩
                Page<TorqueWarnLog> pageTorque = new Page<TorqueWarnLog>(pageNo, pageSize);
                QueryWrapper<TorqueWarnLog> wrapperTorque = new QueryWrapper<>();
                wrapperTorque.lambda().eq(TorqueWarnLog::getJh, jh).orderByDesc(TorqueWarnLog::getWarnStartTime);
                Page<TorqueWarnLog> torqueWarnLogPage = torqueWarnLogService.page(pageTorque, wrapperTorque);
                res = Result.OK(torqueWarnLogPage);
                break;
            case "泵压预警":
                //扭矩
                Page<PumpingPressureWarnLog> pagePumpingPressure = new Page<PumpingPressureWarnLog>(pageNo, pageSize);
                QueryWrapper<PumpingPressureWarnLog> wrapperPumpingPressure = new QueryWrapper<>();
                wrapperPumpingPressure.lambda().eq(PumpingPressureWarnLog::getJh, jh).orderByDesc(PumpingPressureWarnLog::getWarnTime);
                Page<PumpingPressureWarnLog> pumpingPressureWarnLogPage = pumpingPressureWarnLogService.page(pagePumpingPressure, wrapperPumpingPressure);
                res = Result.OK(pumpingPressureWarnLogPage);
                break;
            case "总池体积预警":
                //总池体积
                Page<TotalPoolVolumeWarnLog> pageTotalPoolVolume = new Page<TotalPoolVolumeWarnLog>(pageNo, pageSize);
                QueryWrapper<TotalPoolVolumeWarnLog> wrapperTotalPoolVolume = new QueryWrapper<>();
                wrapperTotalPoolVolume.lambda().eq(TotalPoolVolumeWarnLog::getJh, jh).orderByDesc(TotalPoolVolumeWarnLog::getWarnTime);
                Page<TotalPoolVolumeWarnLog> totalPoolVolumeWarnLogPage = totalPoolVolumeWarnLogService.page(pageTotalPoolVolume, wrapperTotalPoolVolume);
                res = Result.OK(totalPoolVolumeWarnLogPage);
                break;
            default:
                break;
        }
        return res;
    }

    /**
     * 更新井预警信息
     */
    @Override
    public void updateAjhWarnInfo() {
        List<WarnLogStatisticsDto> warnLogCount = getWarnLogCount();
        updateAjhWarnTimeAndWanrCount(warnLogCount);
    }

    public List<WarnLogStatisticsDto> getWarnLogCount() {
        WarnLogCountParams params = new WarnLogCountParams();
        List<WarnLogStatisticsDto> hookLoadWarnLogCount = hookLoadWarnLogService.getWarnLogCount(params);
        List<WarnLogStatisticsDto> pumpingPressureWarnLogCount = pumpingPressureWarnLogService.getWarnLogCount(params);
        List<WarnLogStatisticsDto> torqueWarnLogCount = torqueWarnLogService.getWarnLogCount(params);
        List<WarnLogStatisticsDto> totalPoolVolumeWarnLogCount = totalPoolVolumeWarnLogService.getWarnLogCount(params);
        List<WarnLogStatisticsDto> warnLogCount = new ArrayList<>();
        warnLogCount.addAll(hookLoadWarnLogCount);
        warnLogCount.addAll(pumpingPressureWarnLogCount);
        warnLogCount.addAll(torqueWarnLogCount);
        warnLogCount.addAll(totalPoolVolumeWarnLogCount);
        List<WarnLogStatisticsDto> res = new ArrayList<>();
        Map<String, AggregatedResultDto> stringAggregatedResultDtoMap = groupAndAggregate(warnLogCount);
        for (Map.Entry<String, AggregatedResultDto> entry : stringAggregatedResultDtoMap.entrySet()) {
            WarnLogStatisticsDto model = new WarnLogStatisticsDto();
            String jh = entry.getKey();
            BigDecimal bjcs = entry.getValue().getSum();
            Date zxbjrq = entry.getValue().getMaxDate();
            model.setJh(jh);
            model.setBjcs(bjcs);
            model.setZxbjrq(zxbjrq);
            res.add(model);
        }
        return res;
    }

    public Map<String, AggregatedResultDto> groupAndAggregate(List<WarnLogStatisticsDto> warnLogCount) {
        Map<String, AggregatedResultDto> result = new HashMap<>();
        for (WarnLogStatisticsDto obj : warnLogCount) {
            String group = obj.getJh();
            if (!result.containsKey(group)) {
                result.put(group, new AggregatedResultDto(BigDecimal.ZERO, null));
            }
            AggregatedResultDto aggregated = result.get(group);
            aggregated.setSum(aggregated.getSum().add(obj.getBjcs()));
            if (aggregated.getMaxDate() == null || obj.getZxbjrq().after(aggregated.getMaxDate())) {
                aggregated.setMaxDate(obj.getZxbjrq());
            }
        }
        return result;
    }

    public void updateAjhWarnTimeAndWanrCount(List<WarnLogStatisticsDto> warnLogCount) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<String> jhs = warnLogCount.stream().map(WarnLogStatisticsDto::getJh).collect(Collectors.toList());
        QueryWrapper<Ajh> wrapper = new QueryWrapper<>();
        wrapper.lambda().in(Ajh::getJH, jhs);
        List<Ajh> list = ajhService.list(wrapper);
        log.info("更新前的数据:{}", list);
        list.forEach(model -> {
            String jh = model.getJH();
            List<WarnLogStatisticsDto> collect = warnLogCount.stream().filter(item -> item.getJh().equals(jh)).collect(Collectors.toList());
            if (collect.size() > 0) {
                model.setWARNCOUNT(collect.get(0).getBjcs());
                model.setWARNTIME(sdf.format(collect.get(0).getZxbjrq()));
            }
        });
        log.info("更新后的数据:{}", list);
        ajhService.updateBatchById(list);
    }

    /**
     * 根据井号、时间筛选最新的预警数据
     *
     * @param params
     */
    public void getMaxWarnTimeByJh(HashMap<String, Object> params) {
        String jhs = (String) params.get("jhs");
        List<String> jhList = new ArrayList<>();
        if (!"".equals(jhs)) {
            String[] split = jhs.split(",");
            jhList.addAll(Arrays.asList(split));
        }
    }


    @Override
    public List<WarnLogComprehensiveDto> getMaxTimeWarnDataByJh(HashMap<String, Object> params) {
        List<WarnLogComprehensiveDto> res = new ArrayList<>();
        String jhs = (String) params.get("jhs");
        List<String> jhList = new ArrayList<>();
        if (!"".equals(jhs)) {
            String[] split = jhs.split(",");
            jhList.addAll(Arrays.asList(split));
        }
        String starTime = (String) params.get("strDate");
        String endTime = (String) params.get("endDate");
        log.info("请求井:{};开始时间:{};结束时间:{}",jhs,starTime,endTime);
        String strDate = starTime.replace("/", "-");
        String endDate = endTime.replace("/", "-");
        //根据井号
        jhList.forEach(item -> {
            WarnLogComprehensiveDto maxData = getMaxData(item, strDate + " 00:00:00", endDate + " 23:59:59");
            if (!StringUtils.isEmpty(maxData)) {
                res.add(maxData);
            }
        });
        return res.stream().sorted(Comparator.comparing(WarnLogComprehensiveDto::getStatus).
                thenComparing(WarnLogComprehensiveDto::getZxbjsj, Comparator.reverseOrder())).
                collect(Collectors.toList());
    }

    public WarnLogComprehensiveDto getMaxData(String jh, String starTime, String endTime) {
        WarnLogComprehensiveDto res = null;
        //获取钩载最新预警时间
        QueryWrapper<HookLoadWarnLog> hookLoadWarnLogQueryWrapper = new QueryWrapper<>();
        hookLoadWarnLogQueryWrapper.lambda().eq(HookLoadWarnLog::getJh, jh).and(wrapper1 -> wrapper1
                .apply("WARN_TIME >= TO_DATE({0},'yyyy-MM-dd HH24:mi:ss')", starTime)
                .apply("WARN_TIME <= TO_DATE({0},'yyyy-MM-dd HH24:mi:ss')", endTime).or()
                .apply("MOBIL_DRILLING_TOOLS_START_TIME >= TO_DATE({0},'yyyy-MM-dd HH24:mi:ss')", starTime)
                .apply("MOBIL_DRILLING_TOOLS_START_TIME <= TO_DATE({0},'yyyy-MM-dd HH24:mi:ss')", endTime)
        ).orderByDesc(HookLoadWarnLog::getWarnTime, HookLoadWarnLog::getMobilDrillingToolsStartTime);
        List<HookLoadWarnLog> hookLoadWarnLogList = hookLoadWarnLogService.list(hookLoadWarnLogQueryWrapper);
        //获取扭矩最新预警时间
        QueryWrapper<TorqueWarnLog> torqueWarnLogQueryWrapper = new QueryWrapper<>();
        torqueWarnLogQueryWrapper.lambda().eq(TorqueWarnLog::getJh, jh).and(wrapper1 -> wrapper1
                        .apply("WARN_START_TIME >= TO_DATE({0},'yyyy-MM-dd HH24:mi:ss')", starTime)
                        .apply("WARN_START_TIME <= TO_DATE({0},'yyyy-MM-dd HH24:mi:ss')", endTime)).
                orderByDesc(TorqueWarnLog::getWarnStartTime);
        List<TorqueWarnLog> torqueWarnLogList = torqueWarnLogService.list(torqueWarnLogQueryWrapper);
        //获取泵压最新预警时间
        QueryWrapper<PumpingPressureWarnLog> pumpingPressureWarnLogQueryWrapper = new QueryWrapper<>();
        pumpingPressureWarnLogQueryWrapper.lambda().eq(PumpingPressureWarnLog::getJh, jh).and(wrapper1 -> wrapper1
                        .apply("WARN_TIME >= TO_DATE({0},'yyyy-MM-dd HH24:mi:ss')", starTime)
                        .apply("WARN_TIME <= TO_DATE({0},'yyyy-MM-dd HH24:mi:ss')", endTime)).
                orderByDesc(PumpingPressureWarnLog::getWarnTime);
        List<PumpingPressureWarnLog> pumpingPressureWarnLogList = pumpingPressureWarnLogService.list(pumpingPressureWarnLogQueryWrapper);
        //获取总池体积最新预警时间
        QueryWrapper<TotalPoolVolumeWarnLog> totalPoolVolumeWarnLogQueryWrapper = new QueryWrapper<>();
        totalPoolVolumeWarnLogQueryWrapper.lambda().eq(TotalPoolVolumeWarnLog::getJh, jh).and(wrapper1 -> wrapper1
                        .apply("WARN_TIME >= TO_DATE({0},'yyyy-MM-dd HH24:mi:ss')", starTime)
                        .apply("WARN_TIME <= TO_DATE({0},'yyyy-MM-dd HH24:mi:ss')", endTime)).
                orderByDesc(TotalPoolVolumeWarnLog::getWarnTime);
        List<TotalPoolVolumeWarnLog> totalPoolVolumeWarnLogList = totalPoolVolumeWarnLogService.list(totalPoolVolumeWarnLogQueryWrapper);
        List<WarnLogComprehensiveDto> warnLogComprehensiveDtoList = new ArrayList<>();
        if (hookLoadWarnLogList.size() > 0) {
            Date warnTime = hookLoadWarnLogList.get(0).getWarnTime();
            WarnLogComprehensiveDto model = new WarnLogComprehensiveDto();
            model.setWarnLogId(hookLoadWarnLogList.get(0).getId());
            model.setJh(hookLoadWarnLogList.get(0).getJh());
            model.setZxbjsj(warnTime);
            model.setYjlb("钩载变化异常");
            model.setStatus(hookLoadWarnLogList.get(0).getStatus());
            warnLogComprehensiveDtoList.add(model);
        }
        if (torqueWarnLogList.size() > 0) {
            WarnLogComprehensiveDto model = new WarnLogComprehensiveDto();
            model.setWarnLogId(torqueWarnLogList.get(0).getId());
            model.setJh(torqueWarnLogList.get(0).getJh());
            model.setZxbjsj(torqueWarnLogList.get(0).getWarnStartTime());
            model.setYjlb("扭矩变化异常");
            model.setStatus(torqueWarnLogList.get(0).getStatus());
            warnLogComprehensiveDtoList.add(model);
        }
        if (pumpingPressureWarnLogList.size() > 0) {
            WarnLogComprehensiveDto model = new WarnLogComprehensiveDto();
            model.setWarnLogId(pumpingPressureWarnLogList.get(0).getId());
            model.setJh(pumpingPressureWarnLogList.get(0).getJh());
            model.setZxbjsj(pumpingPressureWarnLogList.get(0).getWarnTime());
            model.setYjlb("泵压变化异常");
            model.setStatus(pumpingPressureWarnLogList.get(0).getStatus());
            warnLogComprehensiveDtoList.add(model);
        }
        if (totalPoolVolumeWarnLogList.size() > 0) {
            WarnLogComprehensiveDto model = new WarnLogComprehensiveDto();
            model.setWarnLogId(totalPoolVolumeWarnLogList.get(0).getId());
            model.setJh(totalPoolVolumeWarnLogList.get(0).getJh());
            model.setZxbjsj(totalPoolVolumeWarnLogList.get(0).getWarnTime());
            model.setYjlb("总池体积变化异常");
            model.setStatus(totalPoolVolumeWarnLogList.get(0).getStatus());
            warnLogComprehensiveDtoList.add(model);
        }
        log.info("排序的数据:{}",warnLogComprehensiveDtoList);
        //获取数组时间最大的一条数据
        if (warnLogComprehensiveDtoList.size() > 0) {
            // 倒序排序
            List<WarnLogComprehensiveDto> sortedList = warnLogComprehensiveDtoList.stream()
                    .sorted(Comparator.comparing(WarnLogComprehensiveDto::getZxbjsj).reversed())
                    .collect(Collectors.toList());
            res = sortedList.get(0);
        }
        return res;
    }

    @Override
    public void updateWarnLogStatusById(String id,String type,String status){
        switch (type){
            case "钩载变化异常":
                HookLoadWarnLog hookLoadWarnLog = hookLoadWarnLogService.getById(id);
                hookLoadWarnLog.setStatus(status);
                hookLoadWarnLogService.updateById(hookLoadWarnLog);
                break;
            case "扭矩变化异常":
                TorqueWarnLog torqueWarnLog = torqueWarnLogService.getById(id);
                torqueWarnLog.setStatus(status);
                torqueWarnLogService.updateById(torqueWarnLog);
                break;
            case "泵压变化异常":
                PumpingPressureWarnLog pumpingPressureWarnLog = pumpingPressureWarnLogService.getById(id);
                pumpingPressureWarnLog.setStatus(status);
                pumpingPressureWarnLogService.updateById(pumpingPressureWarnLog);
                break;
            case "总池体积变化异常":
                TotalPoolVolumeWarnLog totalPoolVolumeWarnLog = totalPoolVolumeWarnLogService.getById(id);
                totalPoolVolumeWarnLog.setStatus(status);
                totalPoolVolumeWarnLogService.updateById(totalPoolVolumeWarnLog);
                break;
            default:
                break;
        }
    };

    @Override
    public void saveWarnOperateLog(String id,String jh,String type){
        WarnOperateLog model=new WarnOperateLog();
        model.setJh(jh);
        model.setWarnLogId(id);
        model.setWarnType(type);
        String sessionCasName = iWellboreAuthQuery.getSessionCasName();
        //根据账户名获取当前登录用户单位信
        WellboreUser user = null;
        String content=model.getJh()+";"+model.getWarnType()+"预警解除";
        try {
            user=iWellboreAuthQuery.queryCasLogginedUserInformation(sessionCasName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if(!StringUtils.isEmpty(user)){
            ENT_USER ent_user = user.getENT_USER();
            log.info("统一认证平台登录用户信息:用户账户{};单位:{};另一个单位:{};所有单位:{}",ent_user.getEntUserName(),
                    ent_user.getOrgnaName(),ent_user.getPOrgnaName(),ent_user.getOrgMap().getOrgnaFullName());
            model.setCreateUser(sessionCasName);
            model.setUserName(ent_user.getEntUserName());
        }
        model.setCreateTime(new Date());
        model.setContent(content);
        String tableNameByType = getTableNameByType(type);
        model.setWarnTableName(tableNameByType);
        updateWarnLogStatusById(id,type,"2");
        warnOperateLogService.save(model);
    }
    public String getTableNameByType(String type){
        String res="";
        switch (type){
            case "钩载变化异常":
                res="HOOK_LOAD_WARN_LOG";
                break;
            case "扭矩变化异常":
                res="TORQUE_WARN_LOG";
                break;
            case "泵压变化异常":
                res="PUMPING_PRESSURE_WARN_LOG";
                break;
            case "总池体积变化异常":
                res="TOTAL_POOL_VOLUME_WARN_LOG";
                break;
            default:
                break;
        }
        return res;
    }

}
