package com.cico.nest.lcdp.boot.core.qxsd.infrastructure.gatewayimpl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.cico.nest.lcdp.boot.core.qxsd.adapter.web.vo.event.EventDetailPageReqVO;
import com.cico.nest.lcdp.boot.core.qxsd.adapter.web.vo.event.EventDetailRespVO;
import com.cico.nest.lcdp.boot.core.qxsd.adapter.ws.AbstractRealTimeEventWs;
import com.cico.nest.lcdp.boot.core.qxsd.adapter.ws.IRealTimeWs;
import com.cico.nest.lcdp.boot.core.qxsd.application.service.EventDetailService;
import com.cico.nest.lcdp.boot.core.qxsd.domain.gateway.EventGateway;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.gatewayimpl.database.EventDetailMapper;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.gatewayimpl.database.dataobject.EventDetailDO;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.gatewayimpl.http.EventMapper;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.gatewayimpl.ws.xlw.vo.RealTimeEventWsVO;
import com.cico.nest.lcdp.framework.common.pojo.PageResult;
import com.cico.nest.lcdp.framework.common.util.date.DateUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author zws
 * @date 2024/8/15
 */
@Slf4j
@Service
public class EventGatewayImpl implements EventGateway {
    @Resource
    private EventMapper eventMapper;
    @Resource
    private EventDetailMapper eventDetailMapper;
    @Resource
    private EventDetailService eventDetailService;


    public final Map<String, IRealTimeWs> realTimeWsMap = new ConcurrentHashMap<>();

    @Override
    public void pushRealTimeEventData(String tunnelId,String eventDetailId) {
        //组装数据并推送
        RealTimeEventWsVO realTimeEventWsVO = new RealTimeEventWsVO()
                // 事件未完成集合
                .setEventThirdEventStatusNotFinishList(this.selectByTunnelIdAndThirdEventStatusNotFinish(tunnelId))
                .setEventCount(this.getEventCount(tunnelId))
                .setEventDetailRespVO(this.getEventDetailById(tunnelId,eventDetailId))
                ;
        String eventDetailJson = JSONObject.toJSONString(realTimeEventWsVO);
//        String eventDetailJson = JSONObject.toJSONString(eventDetailRespList);
        IRealTimeWs realTimeWs = getRealTimeWs(tunnelId);
        log.info("------------------推送开始-----------------");
        log.info("推送事件给前端:{}",eventDetailJson);
        log.info("------------------推送结束-----------------");
        realTimeWs.sendMessage(eventDetailJson);
    }

    @Override
    public List<EventDetailDO> syncEventDetailList(Date startDateTime, Date endDateTime) {
        return eventMapper.syncEventDetailList(startDateTime,endDateTime);
    }

    public IRealTimeWs getRealTimeWs(String tunnelId){
        IRealTimeWs realTimeWs = realTimeWsMap.get(tunnelId);
        if(Objects.isNull(realTimeWs)){
            Map<String, AbstractRealTimeEventWs> beansOfType = SpringUtil.getBeansOfType(AbstractRealTimeEventWs.class);
            if(CollUtil.isNotEmpty(beansOfType)){
                for(Map.Entry<String, AbstractRealTimeEventWs> entry : beansOfType.entrySet()){
                    AbstractRealTimeEventWs abstractRealTimeEventWs = entry.getValue();
                    if(StringUtils.isEmpty(abstractRealTimeEventWs.tunnelId())){
                        log.error("隧道ID为空，无法推送事件数据,class:{}",abstractRealTimeEventWs.getClass().getName());
                    }else{
                        realTimeWsMap.put(abstractRealTimeEventWs.tunnelId(),abstractRealTimeEventWs);
                    }
                }
            }
        }
        return realTimeWsMap.get(tunnelId);
    }

    /**
     * 根据隧道ID查询事件信息
     * 第三方事件状态事件状态  0结束、1预警、2处理中 = != 0 的信息
     * @param tunnelId
     * @return
     */
    public List<EventDetailRespVO> selectByTunnelIdAndThirdEventStatusNotFinish(String tunnelId){
        List<EventDetailDO> eventDetailDOList = eventDetailMapper.selectByTunnelIdAndThirdEventStatusNotFinish(tunnelId);
        return eventDetailDOList.stream().map(eventDetailDO -> {
            EventDetailRespVO eventDetailRespVO = new EventDetailRespVO();
            BeanUtils.copyProperties(eventDetailDO,eventDetailRespVO);
            if(Objects.nonNull(eventDetailDO.getCarInfoList())){
                eventDetailRespVO.setCarInfoList(JSONArray.parseArray(eventDetailDO.getCarInfoList().toJSONString(), EventDetailDO.EventCarInfo.class));
            }
            long diffSecond = DateUtils.diff(new Date(),eventDetailDO.getEventStartTime())/1000;
            int excessSecond = (int)diffSecond % 60;
            int minute = (int)diffSecond / 60;
            eventDetailRespVO.setRetainedTime(minute+"分"+excessSecond+"秒");
            return eventDetailRespVO;
        }).toList();
    }

    /**
     * 查询当前事件总数
     * @param tunnelId
     * @return
     */
    public Long getEventCount(String tunnelId){
        // 查询当前事件列表 未处理完成的总数，这里之间调用列表分页接口
        EventDetailPageReqVO pageReqVO = new EventDetailPageReqVO();
        pageReqVO.setPageNo(1);
        pageReqVO.setPageSize(1);
        pageReqVO.setTunnelId(tunnelId);
        pageReqVO.setEventStatusSearch(0);
        PageResult pageResult = eventDetailMapper.selectPage(pageReqVO);
        if(Objects.nonNull(pageResult)){
            return pageResult.getTotal();
        }
        return 0L;
    }

    /**
     * 查询当前事件
     * @param tunnelId
     * @return
     */
    public EventDetailRespVO getEventDetailById(String tunnelId,String eventDetailId){
        // 查询当前事件列表 未处理完成的总数，这里之间调用列表分页接口
        EventDetailDO eventDetailDO = eventDetailMapper.selectOne(
                EventDetailDO::getId,eventDetailId,
                EventDetailDO::getTunnelId,tunnelId
        );
        if(Objects.nonNull(eventDetailDO)){
            return EventDetailDO.convert2VO(eventDetailDO,"");
        }
        log.error("事件详情查询失败，eventDetailId:{}",eventDetailId);
        return new EventDetailRespVO();
    }

}
