package com.ningdatech.carapi.car.rpt.manage;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.basic.util.NdDateUtils;
import com.ningdatech.carapi.car.rpt.model.dto.RptMonthOverspeedCompanyParamDTO;
import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOfflineParamDTO;
import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOverspeedCompanyParamDTO;
import com.ningdatech.carapi.car.rpt.model.dto.RptMonthSpecialOverspeedVehiclesParamDTO;
import com.ningdatech.carapi.car.rpt.model.po.RptMonthOverspeedCompanyPO;
import com.ningdatech.carapi.car.rpt.model.po.RptMonthOverspeedSpecialVehiclesPO;
import com.ningdatech.carapi.car.rpt.model.po.RptMonthSpecialOfflinePO;
import com.ningdatech.carapi.car.rpt.model.po.RptMonthSpecialVehiclesOverspeedPO;
import com.ningdatech.carapi.car.rpt.model.vo.RptMonthOverspeedCompanyVO;
import com.ningdatech.carapi.car.rpt.model.vo.RptMonthOverspeedSpecialCompanyVO;
import com.ningdatech.carapi.car.rpt.model.vo.RptMonthOverspeedSpecialVehiclesVO;
import com.ningdatech.carapi.car.rpt.model.vo.RptMonthSpecialOfflineVO;
import com.ningdatech.carapi.car.rpt.service.IRptMonthOverspeedCompanyService;
import com.ningdatech.carapi.car.rpt.service.IRptMonthOverspeedSpecialCompanyService;
import com.ningdatech.carapi.car.rpt.service.IRptMonthOverspeedSpecialVehiclesService;
import com.ningdatech.carapi.car.rpt.service.IRptMonthSpecialOfflineService;
import com.ningdatech.carapi.common.util.CodeUtil;
import com.ningdatech.carapi.common.util.ExcelDownUtil;
import com.ningdatech.carapi.common.util.ExcelExportStyle;
import com.ningdatech.carapi.scheduler.entity.VehicleOnlineStatusDay;
import com.ningdatech.carapi.scheduler.service.IVehicleOnlineStatusDayService;
import com.ningdatech.carapi.sys.helper.RegionsCacheHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.List;

/**
 * @author CMM
 * @Classname RptManage
 * @Description
 * @Date 2022/11/8 17:03
 * @Created by PoffyZhang
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class RptMonthManage {
    private final RegionsCacheHelper regionsCacheHelper;
    private final IRptMonthOverspeedCompanyService rptMonthOverspeedCompanyService;
    private final IRptMonthOverspeedSpecialCompanyService rptMonthOverspeedSpecialCompanyService;
    private final IRptMonthOverspeedSpecialVehiclesService rptMonthOverspeedSpecialVehiclesService;
    private final IRptMonthSpecialOfflineService rptMonthSpecialOfflineService;
    private final IVehicleOnlineStatusDayService vehicleOnlineStatusDayService;

    public List<RptMonthOverspeedCompanyVO> monthlyOverspeedCompany(RptMonthOverspeedCompanyParamDTO param) {
        validMonthDays(param);
        List<RptMonthOverspeedCompanyPO> list =  rptMonthOverspeedCompanyService.report(param);
        return CollUtils.convert(list,m ->{
            RptMonthOverspeedCompanyVO vo = BeanUtil.copyProperties(m, RptMonthOverspeedCompanyVO.class);
            CodeUtil.searchRegionName(vo);
            return vo;
        });
    }

    private <T> void validMonthDays(T param) {

        Field startTimeField = null;
        Field endTimeField = null;
        String startTime = null;
        String endTime = null;
        try {
            startTimeField = param.getClass().getDeclaredField("startTime");
            endTimeField = param.getClass().getDeclaredField("endTime");
            startTimeField.setAccessible(Boolean.TRUE);
            endTimeField.setAccessible(Boolean.TRUE);
            startTime = ((String) startTimeField.get(param));
            endTime = ((String) endTimeField.get(param));
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        LocalDate start = NdDateUtils.date2LocalDate(NdDateUtils.parseAsDateTime(startTime));
        LocalDate end = NdDateUtils.date2LocalDate(NdDateUtils.parseAsDateTime(endTime));
        int startYear = start.getYear();
        int endYear = end.getYear();
        if (endYear != startYear){
            throw new BizException("选择日期错误，请重新选择!");
        }
        int startMonth = start.getMonthValue();
        int endMonth = end.getMonthValue();
        if (endMonth != startMonth){
            throw new BizException("选择日期错误，请重新选择!");
        }
        int startDayOfMonth = start.getDayOfMonth();
        int endDayOfMonth = end.getDayOfMonth();
        int days = endDayOfMonth - startDayOfMonth;
        if (days > (int) (NdDateUtils.MAX_MONTH_DAY + 1)){
            throw new BizException("选择日期天数大于31天，请重新选择!");
        }
    }

    public List<RptMonthOverspeedSpecialCompanyVO> monthlySpecialOverspeedCompany(RptMonthSpecialOverspeedCompanyParamDTO param) {
        validMonthDays(param);
        List<RptMonthSpecialVehiclesOverspeedPO> list =  rptMonthOverspeedSpecialCompanyService.report(param);
        return CollUtils.convert(list,m ->{
            RptMonthOverspeedSpecialCompanyVO vo = BeanUtil.copyProperties(m, RptMonthOverspeedSpecialCompanyVO.class);
            CodeUtil.searchRegionName(vo);
            return vo;
        });
    }

    public List<RptMonthSpecialOfflineVO> monthlySpecialOffline(RptMonthSpecialOfflineParamDTO param) {
        // 不允许跨年和跨月,时间区间在某个月内
        validMonthDays(param);
        Page<RptMonthSpecialOfflinePO> page = param.page();

        String startTimeStr = param.getStartTime();
        LocalDateTime startTime = LocalDateTime.parse(startTimeStr, DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN));
        int startDay = startTime.getDayOfYear();
        String endTimeStr = param.getEndTime();
        LocalDateTime endTime = LocalDateTime.parse(endTimeStr, DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN));
        int endDay = endTime.getDayOfYear();

        // 从车辆天在线表中查询出所选时间区间内所有的车辆
        VehicleOnlineStatusDay statusday = new VehicleOnlineStatusDay();
        statusday.setYear(String.valueOf(LocalDateTime.now().getYear()));
        statusday.setMonth(String.valueOf(LocalDateTime.now().getMonthValue()));
        statusday.setDay(String.valueOf(LocalDateTime.now().getDayOfMonth()));
        //vehicleOnlineStatusDayService.listInMonthTable();
        // 计算车辆最大不在线天数



        List<RptMonthSpecialOfflinePO> pageList =  rptMonthSpecialOfflineService.reportPage(page,param);
        if (CollUtil.isEmpty(pageList)){
            return Collections.emptyList();
        }
        return CollUtils.convert(pageList,m ->{
            RptMonthSpecialOfflineVO vo = BeanUtil.copyProperties(m, RptMonthSpecialOfflineVO.class);
            CodeUtil.searchCompanyNameAndRegionName(vo);
            return vo;
        });
    }

    public List<RptMonthOverspeedSpecialVehiclesVO> monthlyOverspeedVehicles(RptMonthSpecialOverspeedVehiclesParamDTO param) {
        validMonthDays(param);
        Page<RptMonthOverspeedSpecialVehiclesPO> page = param.page();
        LocalDate start = NdDateUtils.date2LocalDate(NdDateUtils.parseAsDateTime(param.getStartTime()));
        LocalDate end = NdDateUtils.date2LocalDate(NdDateUtils.parseAsDateTime(param.getEndTime()));
        String lastMonthStartTime = start.minusMonths(1).toString();
        String lastMonthEndTime = end.minusMonths(1).toString();
        param.setLastMonthStartTime(lastMonthStartTime);
        param.setLastMonthEndTime(lastMonthEndTime);
        List<RptMonthSpecialOfflinePO> pageList = rptMonthOverspeedSpecialVehiclesService.reportPage(page,param);
        if (CollUtil.isEmpty(pageList)){
            return Collections.emptyList();
        }
        return CollUtils.convert(pageList,m ->{
            RptMonthOverspeedSpecialVehiclesVO vo = BeanUtil.copyProperties(m, RptMonthOverspeedSpecialVehiclesVO.class);
            CodeUtil.searchCompanyNameAndRegionName(vo);
            return vo;
        });
    }

    public void overSpeedEnterpriseRankMonthReportExport
            (HttpServletResponse response, RptMonthOverspeedCompanyParamDTO param) {
        List<RptMonthOverspeedCompanyVO> collect = monthlyOverspeedCompany(param);
        String fileName = "浙江省超速企业排名月报表";
        ExcelDownUtil.setFileName(fileName, response);
        // 数据导出处理函数
        try {
            EasyExcel.write(response.getOutputStream(), RptMonthOverspeedCompanyVO.class)
                    .autoCloseStream(false)
                    .registerWriteHandler(ExcelExportStyle.formalStyle())
                    .sheet(fileName)
                    .doWrite(collect);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void overSpeedSpecialVehiclesRankMonthReportExport(HttpServletResponse response, RptMonthSpecialOverspeedCompanyParamDTO param) {
        List<RptMonthOverspeedSpecialCompanyVO> collect = monthlySpecialOverspeedCompany(param);
        String fileName = "浙江省超速专用车辆排名月报表";
        ExcelDownUtil.setFileName(fileName, response);
        // 数据导出处理函数
        try {
            EasyExcel.write(response.getOutputStream(), RptMonthOverspeedSpecialCompanyVO.class)
                    .autoCloseStream(false)
                    .registerWriteHandler(ExcelExportStyle.formalStyle())
                    .sheet(fileName)
                    .doWrite(collect);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void specialVehiclesOfflineSortingMonthReportExport(HttpServletResponse response, RptMonthSpecialOfflineParamDTO param) {
        List<RptMonthSpecialOfflineVO> collect = monthlySpecialOffline(param);
        String fileName = "浙江省不上线的专用车辆排序表月报";
        ExcelDownUtil.setFileName(fileName, response);
        // 数据导出处理函数
        try {
            EasyExcel.write(response.getOutputStream(), RptMonthSpecialOfflineVO.class)
                    .autoCloseStream(false)
                    .registerWriteHandler(ExcelExportStyle.formalStyle())
                    .sheet(fileName)
                    .doWrite(collect);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void overSpeedSpecialVehiclesContrastMonthReportExport(HttpServletResponse response, RptMonthSpecialOverspeedVehiclesParamDTO param) {
        List<RptMonthOverspeedSpecialVehiclesVO> collect = monthlyOverspeedVehicles(param);
        String fileName = "浙江省超速专用车辆月对比报表";
        ExcelDownUtil.setFileName(fileName, response);
        // 数据导出处理函数
        try {
            EasyExcel.write(response.getOutputStream(), RptMonthOverspeedSpecialVehiclesVO.class)
                    .autoCloseStream(false)
                    .registerWriteHandler(ExcelExportStyle.formalStyle())
                    .sheet(fileName)
                    .doWrite(collect);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
