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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.basic.util.NdDateUtils;
import com.ningdatech.basic.util.StrPool;
import com.ningdatech.carapi.car.monitor.entity.AlarmDataLoad;
import com.ningdatech.carapi.car.monitor.entity.VehicleSecurityMonitor;
import com.ningdatech.carapi.car.monitor.model.dto.AlarmDataLoadDTO;
import com.ningdatech.carapi.car.monitor.model.dto.LoadMonitorPageParamDTO;
import com.ningdatech.carapi.car.monitor.model.dto.SecurityMonitorExportDTO;
import com.ningdatech.carapi.car.monitor.model.dto.SecurityMonitorPageParamDTO;
import com.ningdatech.carapi.car.monitor.model.vo.AlarmDataLoadVO;
import com.ningdatech.carapi.car.monitor.model.vo.SecurityMonitorVO;
import com.ningdatech.carapi.car.monitor.service.IAlarmDataLoadService;
import com.ningdatech.carapi.car.monitor.service.IVehicleSecurityMonitorService;
import com.ningdatech.carapi.common.aop.BuildChildrenRegionWrapper;
import com.ningdatech.carapi.common.constant.BgTypeEnum;
import com.ningdatech.carapi.common.constant.CommonConstant;
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.datascope.aop.LambdaDataScope;
import com.ningdatech.carapi.sys.entity.dto.CascadeCodeDTO;
import com.ningdatech.carapi.sys.helper.RegionsCacheHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Classname StatusMonitorManage
 * @Description
 * @Date 2022/11/4 16:30
 * @Created by PoffyZhang
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class StatusMonitorManage {

    private final IAlarmDataLoadService alarmDataLoadService;
    private final IVehicleSecurityMonitorService vehicleSecurityMonitorService;
    private final RegionsCacheHelper regionsCacheHelper;

    public PageVo<SecurityMonitorVO> securityMonitorList(SecurityMonitorPageParamDTO param) {
        Page<VehicleSecurityMonitor> page = param.page();
        LambdaQueryWrapper<VehicleSecurityMonitor> wrapper = Wrappers.lambdaQuery(VehicleSecurityMonitor.class);
        wrapper.in(VehicleSecurityMonitor::getAlarmType, BgTypeEnum.listCode(false));
        ((StatusMonitorManage) AopContext.currentProxy()).searchSecurityMonitor(page, wrapper, param);
        if (0L == page.getTotal()) {
            return PageVo.empty();
        }
        List<SecurityMonitorVO> data = CollUtils.convert(page.getRecords(), this::convert);
        return PageVo.of(data, page.getTotal());
    }

    public PageVo<AlarmDataLoadVO> loadMonitorList(LoadMonitorPageParamDTO param) {
        Page<AlarmDataLoad> page = param.page();
        searchLoad(page, param);
        if (0L == page.getTotal()) {
            return PageVo.empty();
        }
        List<AlarmDataLoadVO> data = CollUtils.convert(page.getRecords(), this::convertLoad);
        return PageVo.of(data, page.getTotal());
    }

    @LambdaDataScope(wrapperIndex = 1)
    @BuildChildrenRegionWrapper(entityIndex = 2, wrapperIndex = 1)
    public void searchSecurityMonitor(Page<VehicleSecurityMonitor> page, LambdaQueryWrapper<VehicleSecurityMonitor> wrapper
            , SecurityMonitorPageParamDTO param) {
        wrapper.like(StringUtils.isNotBlank(param.getCarPlate()), VehicleSecurityMonitor::getCarPlate, param.getCarPlate())
                .eq(Objects.nonNull(param.getVehicleType()), VehicleSecurityMonitor::getVehicleType, param.getVehicleType())
                .ge(Objects.nonNull(param.getStartTime()), VehicleSecurityMonitor::getAlarmTime, param.getStartTime())
                .le(Objects.nonNull(param.getEndTime()), VehicleSecurityMonitor::getAlarmTime, param.getEndTime())
                .eq(Objects.nonNull(param.getAlarmType()), VehicleSecurityMonitor::getAlarmType, param.getAlarmType())
                .orderBy(Boolean.TRUE, Boolean.FALSE, VehicleSecurityMonitor::getAlarmTime);
        vehicleSecurityMonitorService.page(page, wrapper);
    }

    private void searchLoad(Page<AlarmDataLoad> page, LoadMonitorPageParamDTO param) {
        LambdaQueryWrapper<AlarmDataLoad> wrapper = Wrappers.lambdaQuery(AlarmDataLoad.class);
        StatusMonitorManage clazz = (StatusMonitorManage) AopContext.currentProxy();
        clazz.searchLoadWrapper(page, wrapper, param);
    }

    @LambdaDataScope(wrapperIndex = 1)
    @BuildChildrenRegionWrapper(entityIndex = 2, wrapperIndex = 1)
    public void searchLoadWrapper(Page<AlarmDataLoad> page, LambdaQueryWrapper<AlarmDataLoad> wrapper, LoadMonitorPageParamDTO param) {
        wrapper.like(StringUtils.isNotBlank(param.getPlateNo()), AlarmDataLoad::getPlateNo, param.getPlateNo())
                .ge(Objects.nonNull(param.getStartTime()), AlarmDataLoad::getAlarmTime, param.getStartTime())
                .le(Objects.nonNull(param.getEndTime()), AlarmDataLoad::getAlarmTime, param.getEndTime())
                .orderBy(Boolean.TRUE, Boolean.FALSE, AlarmDataLoad::getAlarmTime);
        alarmDataLoadService.page(page, wrapper);
    }

    private SecurityMonitorVO convert(VehicleSecurityMonitor securityMonitor) {
        if (Objects.isNull(securityMonitor)) {
            return null;
        }
        SecurityMonitorVO vo = BeanUtil.copyProperties(securityMonitor, SecurityMonitorVO.class);
        if (StrUtil.startWith(vo.getPictureUrl(), StrPool.HTTP)) {
            vo.setPictureUrl(null);
        }
        if (StrUtil.startWith(vo.getVideoUrl(), StrPool.HTTP)) {
            vo.setVideoUrl(null);
        }
        CodeUtil.searchCompanyNameAndRegionName(vo);
        return vo;
    }

    private AlarmDataLoadVO convertLoad(AlarmDataLoad data) {
        if (Objects.isNull(data)) {
            return null;
        }
        AlarmDataLoadVO vo = BeanUtil.copyProperties(data, AlarmDataLoadVO.class);
        CodeUtil.searchCompanyNameAndRegionName(vo);
        return vo;
    }

    public List<CascadeCodeDTO> alarmTypes() {
        return Arrays.stream(BgTypeEnum.values())
                .filter(w -> !w.getHidden())
                .map(w -> CascadeCodeDTO.of(String.valueOf(w.getCode()), w.getDesc()))
                .collect(Collectors.toList());
    }

    public void exportSecurityMonitor(HttpServletResponse response, SecurityMonitorPageParamDTO param) {
        param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE);
        PageVo<SecurityMonitorVO> page = securityMonitorList(param);
        List<SecurityMonitorExportDTO> collect = page.getRecords().stream()
                .map(w -> {
                    SecurityMonitorExportDTO monitorExportDTO = new SecurityMonitorExportDTO();
                    BeanUtils.copyProperties(w, monitorExportDTO);
                    String timeStr = NdDateUtils.format(w.getAlarmTime(), NdDateUtils.DEFAULT_DATE_TIME_FORMAT);
                    monitorExportDTO.setAlarmTime(timeStr);
                    return monitorExportDTO;
                })
                .collect(Collectors.toList());
        String fileName = "状态监控列表";
        ExcelDownUtil.setFileName(fileName, response);
        // 数据导出处理函数
        try {
            EasyExcel.write(response.getOutputStream(), SecurityMonitorExportDTO.class)
                    .autoCloseStream(false)
                    .registerWriteHandler(ExcelExportStyle.formalStyle())
                    .sheet(fileName)
                    .doWrite(collect);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void exportLoadMonitor(HttpServletResponse response, LoadMonitorPageParamDTO param) {
        param.page(CommonConstant.EXPORT_PAGE_NUMBER, CommonConstant.EXPORT_PAGE_SIZE);
        PageVo<AlarmDataLoadVO> page = loadMonitorList(param);
        List<AlarmDataLoadVO> collect = page.getRecords().stream().map(w -> BeanUtil.copyProperties(w, AlarmDataLoadVO.class)).collect(Collectors.toList());
        String fileName = "载重监控列表";
        ExcelDownUtil.setFileName(fileName, response);
        // 数据导出处理函数
        try {
            EasyExcel.write(response.getOutputStream(), AlarmDataLoadDTO.class)
                    .autoCloseStream(false)
                    .registerWriteHandler(ExcelExportStyle.formalStyle())
                    .sheet(fileName)
                    .doWrite(collect);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
