/*
 * Author: wangjian
 * 生成ServiceImpl
 */
package com.tofly.gpsboot.service.fill.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.system.AuditSateEnum;
import com.tofly.gpsboot.common.system.AuditTypeEnum;
import com.tofly.gpsboot.common.system.MessageTopicEnum;
import com.tofly.gpsboot.common.system.UserTaskStateEnumEnum;
import com.tofly.gpsboot.mapper.fill.FillMonthMapper;
import com.tofly.gpsboot.service.fill.*;
import com.tofly.gpsboot.service.mq.IAuditMessageService;
import com.tofly.gpsboot.service.mq.IReportMessageService;
import com.tofly.gpsboot.service.paln.CheckhistoryService;
import com.tofly.gpsboot.util.DateTimeUtil;
import com.tofly.pojo.fill.*;
import com.tofly.pojo.message.Usertask;
import com.tofly.pojo.plan.dto.ReportAuditDto;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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


@Service("fillMonthService")
public class FillMonthServiceImpl extends ServiceImpl<FillMonthMapper, FillMonth> implements FillMonthService {
    @Autowired
    private IReportMessageService iReportMessageService;

    @Autowired
    private CheckhistoryService checkhistoryService;

    @Autowired
    private IAuditMessageService iAuditMessageService;

    @Autowired
    private UserTaskClient userTaskClient;

    @Autowired
    private FillEcService fillEcService;

    @Autowired
    private FillSludgeDealService fillSludgeDealService;

    @Autowired
    private FillSludgeTransferService fillSludgeTransferService;

    @Autowired
    private FillStcService fillStcService;

    @Autowired
    private FillWaterService fillWaterService;

    @Override
    public Page<FillMonth> getFillMonthPage(Page page, FillMonth fillMonth) {
        Page<FillMonth> fillMonthPage = baseMapper.getFillMonthPage(page,fillMonth);
        fillMonthPage.getRecords().forEach(info -> {
            info.setTotalCsMoM(100f);
            info.setTotalPrMoM(100f);
            info.setTotalDaMoM(100f);
            info.setTotalCsYoY(100f);
            info.setTotalPrYoY(100f);
            info.setTotalDaYoY(100f);

            fillMonth.setBelongStationIds(String.valueOf(info.getBelongStationId()));

            Calendar calendar = Calendar.getInstance();
            calendar.setTime(info.getRecordTime());
            calendar.add(Calendar.MONTH, -1);
            fillMonth.setMonthSel(DateUtil.format(calendar.getTime(), "yyyy-MM"));
            fillMonth.setStartTime(null);
            fillMonth.setEndTime(null);
            List<FillMonth> fillMonthMoMList = baseMapper.getFillMonthPage(fillMonth);
            if (CollUtil.isNotEmpty(fillMonthMoMList)) {
                FillMonth one = fillMonthMoMList.get(0);
                info.setTotalCsMoM(getYoyOrMomRate(new BigDecimal(info.getTotalCs()), new BigDecimal(one.getTotalCs())));
                info.setTotalPrMoM(getYoyOrMomRate(new BigDecimal(info.getTotalPr()), new BigDecimal(one.getTotalPr())));
                info.setTotalDaMoM(getYoyOrMomRate(new BigDecimal(info.getTotalDa()), new BigDecimal(one.getTotalDa())));
            }

            calendar.add(Calendar.YEAR, -1);
            calendar.add(Calendar.MONTH, +1);
            fillMonth.setMonthSel(DateUtil.format(calendar.getTime(), "yyyy-MM"));
            List<FillMonth> fillMonthYoYList = baseMapper.getFillMonthPage(fillMonth);
            if (CollUtil.isEmpty(fillMonthYoYList)) {
                return;
            }
            FillMonth one = fillMonthYoYList.get(0);
            info.setTotalCsYoY(getYoyOrMomRate(new BigDecimal(info.getTotalCs()), new BigDecimal(one.getTotalCs())));
            info.setTotalPrYoY(getYoyOrMomRate(new BigDecimal(info.getTotalPr()), new BigDecimal(one.getTotalPr())));
            info.setTotalDaYoY(getYoyOrMomRate(new BigDecimal(info.getTotalDa()), new BigDecimal(one.getTotalDa())));
        });
        return fillMonthPage;
    }

    @Override
    public boolean saveFillMonth(FillMonth fillMonth) {
        // 判断是否上报
        String report = fillMonth.getReport();
        if("1".equals(report)){
            fillMonth.setState("1");
            this.saveOrUpdate(fillMonth);
            // 通知审核对象mq消息
            iReportMessageService.reportFillMonth(fillMonth.getId(), fillMonth.getAuditUser());
        }else {
            this.saveOrUpdate(fillMonth);
        }
        return true;
    }

    @Override
    public boolean updateFillMonth(FillMonth fillMonth) {
        // 判断是否上报
        String report = fillMonth.getReport();
        if("1".equals(report)){
            fillMonth.setState("1");
            this.saveOrUpdate(fillMonth);
            // 通知审核对象mq消息
            iReportMessageService.reportFillMonth(fillMonth.getId(), fillMonth.getAuditUser());
        }else {
            this.saveOrUpdate(fillMonth);
        }
        return true;
    }

    @Override
    public boolean auditFillMonth(Long id, Long auditUserId, String auditNote, String auditState) {
        FillMonth fillMonth = this.getById(id);
        fillMonth.setAuditState(auditState);
        fillMonth.setAuditNote(auditNote);
        Date date = new Date();
        fillMonth.setAuditTime(date);
        fillMonth.setAuditUser(auditUserId);
        // 判断审核是否通过
        if(AuditSateEnum.AUDIT_YES.getCode().equals(auditState)){
            // 通过 状态改为完成
            fillMonth.setState("2");
        }else {
            // 不通过 上报状态改为0 流程状态改为未上报
            fillMonth.setReport("0");
            fillMonth.setState("0");
        }
        this.updateById(fillMonth);
        // 存入当前计划审批历史信息
        checkhistoryService.recordHis(AuditTypeEnum.AUDIT_TYPE_REPAIR_FILL_MONTH.getCode(), id, auditState, auditNote, auditUserId, date);
        // 发送mq消息(月计划审核成功/失败)给上报对象到消息提示列表
        // 通知审核对象mq消息
        ReportAuditDto dto = new ReportAuditDto();
        dto.setId(fillMonth.getId());
        dto.setAuditId(auditUserId);
        dto.setAuditNotes(auditNote);
        dto.setAuditResult(auditState);
        iAuditMessageService.auditTypeRepairFillMonth(dto,fillMonth.getFillUser());
        // 待办事项处理状态置为完成
        Usertask usertask = new Usertask();
        usertask.setTableName(MessageTopicEnum.REPORT_REPAIR_FILL_MONTH.getTableName());
        usertask.setHandleUser(SecurityUtils.getUserId());
        usertask.setTableId(id);
        List<Usertask> result = userTaskClient.getUserTaskInfo(usertask).getResult();
        if(null != result && result.size()>0){
            Usertask task = result.get(0);
            task.setHandleTime(DateTimeUtil.convertLDTToDate(LocalDateTime.now()));
            task.setHandleUser(SecurityUtils.getUserId());
            task.setIshandle(UserTaskStateEnumEnum.IS_HANDLER_COMPLETED.getCode());
            userTaskClient.updateById(task);
        }
        return true;
    }

    @Override
    public List<FillVo> getIndexValDay(String startDate, String endDate, List<Long> sewageIds) {
        List<Date> dates = findDates(DateUtil.parse(startDate, "yyyy-MM-dd HH:mm:ss"), DateUtil.parse(endDate, "yyyy-MM-dd HH:mm:ss"), 1);
        List<FillVo> stationDeptList = this.baseMapper.getStationDeptList(sewageIds);
        List<FillEc> fillEcs = fillEcService.list(new QueryWrapper<FillEc>().lambda()
                .le(FillEc::getRecordTime, DateUtil.parse(endDate, "yyyy-MM-dd HH:mm:ss"))
                .ge(FillEc::getRecordTime, DateUtil.parse(startDate, "yyyy-MM-dd HH:mm:ss")));
        List<FillSludgeDeal> fillSludgeDeals = fillSludgeDealService.list(new QueryWrapper<FillSludgeDeal>().lambda()
                .le(FillSludgeDeal::getRecordTime, DateUtil.parse(endDate, "yyyy-MM-dd HH:mm:ss"))
                .ge(FillSludgeDeal::getRecordTime, DateUtil.parse(startDate, "yyyy-MM-dd HH:mm:ss")));
//        List<FillSludgeTransfer> fillSludgeTransfers = fillSludgeTransferService.list(new QueryWrapper<FillSludgeTransfer>().lambda()
//                .le(FillSludgeTransfer::getRecordTime, DateUtil.parse(endDate, "yyyy-MM-dd HH:mm:ss"))
//                .ge(FillSludgeTransfer::getRecordTime, DateUtil.parse(startDate, "yyyy-MM-dd HH:mm:ss")));
        List<FillStc> fillStcs = fillStcService.list(new QueryWrapper<FillStc>().lambda()
                .le(FillStc::getRecordTime, DateUtil.parse(endDate, "yyyy-MM-dd HH:mm:ss"))
                .ge(FillStc::getRecordTime, DateUtil.parse(startDate, "yyyy-MM-dd HH:mm:ss")));
        List<FillWater> fillWaters = fillWaterService.list(new QueryWrapper<FillWater>().lambda()
                .le(FillWater::getRecordTime, DateUtil.parse(endDate, "yyyy-MM-dd HH:mm:ss"))
                .ge(FillWater::getRecordTime, DateUtil.parse(startDate, "yyyy-MM-dd HH:mm:ss")));
        List<FillVo> res = new ArrayList<>();
        dates.forEach(info -> stationDeptList.forEach(fillVo -> {
            FillVo fillVoRes = new FillVo();
            BeanUtils.copyProperties(fillVo,fillVoRes);
            fillVoRes.setRecordTime(DateUtil.format(info, "yyyy-MM-dd HH:mm:ss"));
            if (CollUtil.isNotEmpty(fillEcs)) {
                List<FillEc> fillEcsFinal = fillEcs.stream().filter(e -> DateUtil.format(e.getRecordTime(), "yyyy-MM-dd HH:mm:ss").equals(DateUtil.format(info, "yyyy-MM-dd HH:mm:ss"))
                        && Objects.equals(e.getBelongStationId(), fillVo.getBelongStationId())).collect(Collectors.toList());
                fillVoRes.setElectro(CollUtil.isNotEmpty(fillEcsFinal) ? fillEcsFinal.get(0).getElectro() : "0");
            }
            if (CollUtil.isNotEmpty(fillSludgeDeals)) {
                List<FillSludgeDeal> fillSludgeDealsFinal = fillSludgeDeals.stream().filter(e -> DateUtil.format(e.getRecordTime(), "yyyy-MM-dd HH:mm:ss").equals(DateUtil.format(info, "yyyy-MM-dd HH:mm:ss"))
                        && Objects.equals(e.getBelongStationId(), fillVo.getBelongStationId())).collect(Collectors.toList());
                fillVoRes.setDaySludgeDehydration(CollUtil.isNotEmpty(fillSludgeDealsFinal) ? fillSludgeDealsFinal.get(0).getDaySludgeDehydration() : "0");
                fillVoRes.setDaySludgeTransfer(CollUtil.isNotEmpty(fillSludgeDealsFinal) ? fillSludgeDealsFinal.get(0).getDaySludgeTransfer() : "0");
                fillVoRes.setSludgeWaterCutRate(CollUtil.isNotEmpty(fillSludgeDealsFinal) ? fillSludgeDealsFinal.get(0).getSludgeWaterCutRate() : "0");
            }
//            if (CollUtil.isNotEmpty(fillSludgeTransfers)) {
//                List<FillSludgeTransfer> fillSludgeTransfersFinal = fillSludgeTransfers.stream().filter(e -> DateUtil.format(e.getRecordTime(), "yyyy-MM-dd HH:mm:ss").equals(DateUtil.format(info, "yyyy-MM-dd HH:mm:ss"))).collect(Collectors.toList());
//            }
            if (CollUtil.isNotEmpty(fillStcs)) {
                List<FillStc> fillStcsFinal = fillStcs.stream().filter(e -> DateUtil.format(e.getRecordTime(), "yyyy-MM-dd HH:mm:ss").equals(DateUtil.format(info, "yyyy-MM-dd HH:mm:ss"))
                        && Objects.equals(e.getBelongStationId(), fillVo.getBelongStationId())).collect(Collectors.toList());
                fillVoRes.setDayIntoWater(CollUtil.isNotEmpty(fillStcsFinal) ? fillStcsFinal.get(0).getDayIntoWater() : "0");
                fillVoRes.setDayOutWater(CollUtil.isNotEmpty(fillStcsFinal) ? fillStcsFinal.get(0).getDayOutWater() : "0");
            }
            if (CollUtil.isNotEmpty(fillWaters)) {
                List<FillWater> fillWatersFinal = fillWaters.stream().filter(e -> DateUtil.format(e.getRecordTime(), "yyyy-MM-dd HH:mm:ss").equals(DateUtil.format(info, "yyyy-MM-dd HH:mm:ss"))
                        && Objects.equals(e.getBelongStationId(), fillVo.getBelongStationId())).collect(Collectors.toList());
                fillVoRes.setBod5(CollUtil.isNotEmpty(fillWatersFinal) ? fillWatersFinal.get(0).getBod5() : "0");
                fillVoRes.setBod5Out(CollUtil.isNotEmpty(fillWatersFinal) ? fillWatersFinal.get(0).getBod5Out() : "0");
                fillVoRes.setCodCr(CollUtil.isNotEmpty(fillWatersFinal) ? fillWatersFinal.get(0).getCodCr() : "0");
                fillVoRes.setCodCrOut(CollUtil.isNotEmpty(fillWatersFinal) ? fillWatersFinal.get(0).getCodCrOut() : "0");
                fillVoRes.setNh3n(CollUtil.isNotEmpty(fillWatersFinal) ? fillWatersFinal.get(0).getNh3n() : "0");
                fillVoRes.setNh3nOut(CollUtil.isNotEmpty(fillWatersFinal) ? fillWatersFinal.get(0).getNh3nOut() : "0");
                fillVoRes.setPh(CollUtil.isNotEmpty(fillWatersFinal) ? fillWatersFinal.get(0).getPh() : "0");
                fillVoRes.setPhOut(CollUtil.isNotEmpty(fillWatersFinal) ? fillWatersFinal.get(0).getPhOut() : "0");
                fillVoRes.setSs(CollUtil.isNotEmpty(fillWatersFinal) ? fillWatersFinal.get(0).getSs() : "0");
                fillVoRes.setSsOut(CollUtil.isNotEmpty(fillWatersFinal) ? fillWatersFinal.get(0).getSsOut() : "0");
                fillVoRes.setTn(CollUtil.isNotEmpty(fillWatersFinal) ? fillWatersFinal.get(0).getTn() : "0");
                fillVoRes.setTnOut(CollUtil.isNotEmpty(fillWatersFinal) ? fillWatersFinal.get(0).getTnOut() : "0");
                fillVoRes.setTp(CollUtil.isNotEmpty(fillWatersFinal) ? fillWatersFinal.get(0).getTp() : "0");
                fillVoRes.setTpOut(CollUtil.isNotEmpty(fillWatersFinal) ? fillWatersFinal.get(0).getTpOut() : "0");
            }
            res.add(fillVoRes);
        }));
        return res;
    }

//    @Override
//    public List<FillVo> getIndexValMonth(String startMonth, String endMonth) {
//        return this.baseMapper.getIndexValMonth(startMonth, endMonth);
//    }

    @Override
    public List<FillMonth> getIndexValYear(String startYear, String endYear, List<Long> sewageIds) {
        List<FillMonth> fillMonthList = this.baseMapper.getIndexValYear(startYear, endYear, sewageIds);
        fillMonthList.forEach(info -> {
            info.setTotalCsYoY(100f);
            info.setTotalPrYoY(100f);
            info.setTotalDaYoY(100f);

            List<Long> stationIds = new ArrayList<>();
            stationIds.add(info.getBelongStationId());

            Calendar calendar = Calendar.getInstance();
            calendar.setTime(DateUtil.parse(info.getScadaTime(), "yyyy"));
            calendar.add(Calendar.YEAR, -1);
            List<FillMonth> fillMonthYoYList = this.baseMapper.getIndexValYear(
                    DateUtil.format(calendar.getTime(), "yyyy"),
                    DateUtil.format(calendar.getTime(), "yyyy"),
                    stationIds);
            if (CollUtil.isEmpty(fillMonthYoYList)) {
                return;
            }
            FillMonth one = fillMonthYoYList.get(0);
            info.setTotalCsYoY(getYoyOrMomRate(new BigDecimal(info.getTotalCs()), new BigDecimal(one.getTotalCs())));
            info.setTotalPrYoY(getYoyOrMomRate(new BigDecimal(info.getTotalPr()), new BigDecimal(one.getTotalPr())));
            info.setTotalDaYoY(getYoyOrMomRate(new BigDecimal(info.getTotalDa()), new BigDecimal(one.getTotalDa())));
        });
        return fillMonthList;
    }

    /**
     * 获取日期列表
     *
     * @param start 开始时间:2022-01-01 00:00:00
     * @param end   结束时间:2022-10-01 14:00:00
     * @param type  统计类型(0小时，1天，2月)
     * @return
     */
    public static List<Date> findDates(Date start, Date end, Integer type) {
        Calendar s = Calendar.getInstance();
        s.setTime(start);
        Calendar e = Calendar.getInstance();
        e.setTime(end);
        if (s.get(Calendar.YEAR) == e.get(Calendar.YEAR)
                && s.get(Calendar.MONTH) == e.get(Calendar.MONTH)
                && s.get(Calendar.DAY_OF_MONTH) == e.get(Calendar.DAY_OF_MONTH)
                && s.get(Calendar.HOUR_OF_DAY) == e.get(Calendar.HOUR_OF_DAY)
                && type == 0) {
            List<Date> dates = new ArrayList<>();
            dates.add(start);
            return dates;
        }
        if (s.get(Calendar.YEAR) == e.get(Calendar.YEAR)
                && s.get(Calendar.MONTH) == e.get(Calendar.MONTH)
                && s.get(Calendar.DAY_OF_MONTH) == e.get(Calendar.DAY_OF_MONTH)
                && type == 1) {
            List<Date> dates = new ArrayList<>();
            dates.add(start);
            return dates;
        }
        if (s.get(Calendar.YEAR) == e.get(Calendar.YEAR)
                && s.get(Calendar.MONTH) == e.get(Calendar.MONTH)
                && type == 2) {
            List<Date> dates = new ArrayList<>();
            dates.add(start);
            return dates;
        }
        //结束时间在开始时间之后
        List<Date> dates = new ArrayList<>();
        dates.add(s.getTime());
        while (end.getTime() >= s.getTime().getTime()) {
            if (type == 0) {
                s.add(Calendar.HOUR_OF_DAY, 1);
            } else if (type == 1) {
                s.add(Calendar.DAY_OF_MONTH, 1);
            } else if (type == 2) {
                s.add(Calendar.MONTH, 1);
            }
            dates.add(s.getTime());
        }
        dates.remove(dates.size() - 1);
        return dates;
    }

    /**
     *
     * @param up 当年/当月数据值
     * @param low 去年/上月数据值
     * @return
     * @description 计算同比环比增长率
     */
    public float getYoyOrMomRate(BigDecimal up, BigDecimal low) {
        if (low.doubleValue() == 0) {
            return 100f;
        }
        BigDecimal marginVal = up.subtract(low);
        return marginVal.divide(low, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)).floatValue();
    }

}
