package com.gci.boot.modules.gis.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;

import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gci.boot.common.util.DateUtils;
import com.gci.boot.common.util.FormatUtil;
import com.gci.boot.common.util.RedisKey;
import com.gci.boot.common.util.RedisUtil;
import com.gci.boot.enums.AlarmCountType;
import com.gci.boot.enums.AlarmType;
import com.gci.boot.exception.GciBootException;
import com.gci.boot.modules.gis.dto.VehicleFaultDto;
import com.gci.boot.modules.gis.entity.TbGisRunningbus;
import com.gci.boot.modules.gis.entity.TbGisVehicleFaultAlarm;
import com.gci.boot.modules.gis.mapper.TbGisVehicleFaultAlarmMapper;
import com.gci.boot.modules.gis.service.ITbGisRunningbusService;
import com.gci.boot.modules.gis.service.ITbGisVehicleFaultAlarmService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gci.boot.modules.gis.vo.VehicleFaultVo;
import com.gci.boot.modules.statis.vo.AlarmTrendVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 车辆车机故障异常记录表 服务实现类
 * </p>
 *
 * @author 2464
 * @since 2023-09-09
 */
@Service
public class TbGisVehicleFaultAlarmServiceImpl extends ServiceImpl<TbGisVehicleFaultAlarmMapper, TbGisVehicleFaultAlarm> implements ITbGisVehicleFaultAlarmService {

    @Resource
    private TbGisVehicleFaultAlarmMapper gisVehicleFaultAlarmMapper;
    @Autowired
    private ITbGisRunningbusService gisRunningbusService;

    @Override
    public List<VehicleFaultVo> countFault(String projectId) {
        List<VehicleFaultDto> vehicleFaultDtos = new ArrayList<>();
        AlarmCountType[] values = AlarmCountType.values();
        for (AlarmCountType value : values) {
            VehicleFaultDto vehicleFaultDto = new VehicleFaultDto();
            vehicleFaultDto.setName(value.getName());
            vehicleFaultDto.setCountList(value.getAlarmTypeList().stream().map(AlarmType::getDescription).collect(Collectors.toList()));
            vehicleFaultDtos.add(vehicleFaultDto);
        }
        List<VehicleFaultVo> vehicleFaultVo = gisVehicleFaultAlarmMapper.countFault(projectId, vehicleFaultDtos);
        if (vehicleFaultVo.size() < vehicleFaultDtos.size()) {
            for (VehicleFaultDto vehicleFaultDto : vehicleFaultDtos) {
                VehicleFaultVo vo = vehicleFaultVo.stream().filter(v -> v.getName().equals(vehicleFaultDto.getName())).findFirst().orElse(new VehicleFaultVo());
                if (BeanUtil.isEmpty(vo)) {
                    vo.setCount(0);
                    vo.setName(vehicleFaultDto.getName());
                }
                vehicleFaultVo.add(vo);
            }
        }
        return vehicleFaultVo;
    }

    @Override
    public IPage<TbGisVehicleFaultAlarm> pageBuild(Page<TbGisVehicleFaultAlarm> page, LambdaQueryWrapper<TbGisVehicleFaultAlarm> lambdaQueryWrapper) {
        Page<TbGisVehicleFaultAlarm> list = gisVehicleFaultAlarmMapper.pageBuild(page, lambdaQueryWrapper);
        for (TbGisVehicleFaultAlarm record : list.getRecords()) {
            String duration = FormatUtil.formattedTimeDifference(record.getAlarmStartTime(), record.getAlarmEndTime());
            record.setDuration(duration);
        }
        return list;
    }

    @Override
    public List<TbGisVehicleFaultAlarm> findListByTime(Date startTime, Date endTime) {
        LambdaQueryWrapper<TbGisVehicleFaultAlarm> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.between(TbGisVehicleFaultAlarm::getAlarmStartTime, startTime, endTime);
        List<TbGisVehicleFaultAlarm> list = this.gisVehicleFaultAlarmMapper.selectList(queryWrapper);
        return list;
    }

    @Override
    public List<AlarmTrendVO> findTrendListByTime(Date startTime, Date endTime) {
        return this.gisVehicleFaultAlarmMapper.findTrendListByTime(DateUtils.formatTime(startTime), DateUtils.formatTime(endTime));
    }

    @Override
    public void close(String ids, String remark) {
        List<String> split = StrUtil.split(ids, StrUtil.COMMA);
        List<TbGisVehicleFaultAlarm> list = list(new LambdaQueryWrapper<TbGisVehicleFaultAlarm>().in(TbGisVehicleFaultAlarm::getId, split));
        if (list.size() < split.size()) {
            throw new GciBootException("id错误！");
        }
        TbGisVehicleFaultAlarm find = list.stream().filter(i -> i.getIsClosed() == 1).findAny().orElse(null);
        if (find != null) {
            throw new GciBootException("数据中有已关闭告警！请刷新后重新勾选！");
        }
        DateTime dateTime = new DateTime();
        JSONObject jsonObject = new JSONObject();
        jsonObject.set("status", true);
        jsonObject.set("time", dateTime.toString());
        jsonObject.set("endTime", dateTime.toString());
        HashMap<String, Object> needSet = new HashMap<>(list.size());
        for (TbGisVehicleFaultAlarm faultAlarm : list) {
            needSet.put(RedisKey.VEHICLE_IS_FAULT_ALARM + faultAlarm.getPlateNumber() + ":" + faultAlarm.getFaultType(),jsonObject.toString());
            faultAlarm.setIsClosed(1);
            faultAlarm.setCloseType("2");
            faultAlarm.setAlarmEndTime(dateTime);
            faultAlarm.setCloseTime(dateTime);
            faultAlarm.setRemark(remark);
            gisRunningbusService.update(new LambdaUpdateWrapper<TbGisRunningbus>().eq(TbGisRunningbus::getPlateNumber,faultAlarm.getPlateNumber())
                    .set(TbGisRunningbus::getFaultAlarm,checkFaultAlarm(faultAlarm.getPlateNumber())));
        }
        RedisUtil.multiSet(needSet);
        updateBatchById(list);

    }

    private Integer checkFaultAlarm(String plateNumber) {
        int integer = 0;
        AlarmType[] values = AlarmType.values();
        List<String> collect = new ArrayList<String>();
        for (AlarmType value : values) {
            collect.add(RedisKey.VEHICLE_IS_FAULT_ALARM + plateNumber + ":" + value.getProp());
        }
        List<Object> objects = RedisUtil.multiGet(collect);
        if (ObjectUtil.isNotEmpty(objects)) {
            for (Object object : objects) {
                JSONObject jsonObject = new JSONObject(StrUtil.removeAll(StrUtil.strip(Convert.toStr(object), "\""),"\\"));
                if (ObjectUtil.isNotEmpty(jsonObject)) {
                    Boolean status = jsonObject.getBool("status");
                    if (status) {
                        integer = 1;
                        return integer;
                    }
                }
            }
        }
        return integer;
    }
}
