package com.cico.nest.lcdp.boot.core.qxsd.adapter.web;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson2.JSONObject;
import com.cico.nest.lcdp.boot.core.qxsd.adapter.web.vo.event.EventDetailAlarmVO;
import com.cico.nest.lcdp.boot.core.qxsd.adapter.web.vo.event.EventDetailDispelReqVO;
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.web.vo.event.EventHisRespVO;
import com.cico.nest.lcdp.boot.core.qxsd.application.service.EventDetailService;
import com.cico.nest.lcdp.boot.core.qxsd.application.service.HistoryService;
import com.cico.nest.lcdp.boot.core.qxsd.domain.gateway.EventGateway;
import com.cico.nest.lcdp.boot.core.qxsd.domain.gateway.HistoryGateway;
import com.cico.nest.lcdp.boot.core.qxsd.domain.vehicle.TunnelRealTimeVehicle;
import com.cico.nest.lcdp.boot.core.qxsd.domain.vehicle.VehicleInfo;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.common.constatnt.RedisConstants;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.common.constatnt.XlwConstants;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.common.result.XlwResultData;
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.database.dataobject.EventHisDO;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.gatewayimpl.http.ISdgkApiService;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.gatewayimpl.http.sdgk.dto.SdgkEventAlarmDTO;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.gatewayimpl.http.xlw.XlwEventMapper;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.gatewayimpl.http.xlw.dto.XlwBayonetPictureDTO;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.gatewayimpl.http.xlw.dto.XlwBayonetPictureSearchDTO;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.gatewayimpl.http.xlw.dto.XlwPageDTO;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.gatewayimpl.http.xlw.feign.XlwClientFeign;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.gatewayimpl.http.sdgk.dto.SdgkEventAlarmResourceDTO;
import com.cico.nest.lcdp.framework.common.exception.ServiceException;
import com.cico.nest.lcdp.framework.common.pojo.CommonResult;
import com.cico.nest.lcdp.framework.common.pojo.PageResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import static com.cico.nest.lcdp.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR;
import static com.cico.nest.lcdp.framework.common.pojo.CommonResult.success;


@Tag(name = "管理后台 - 事件详情")
@RestController
@RequestMapping("/qxsd/event-detail")
@Validated
@Slf4j
public class EventDetailController {

    @Resource
    private EventDetailService eventDetailService;
    @Resource
    private EventGateway eventGateway;
    @Resource
    private XlwEventMapper xlwEventMapper;
    @Resource
    private HistoryGateway historyGateway;
    @Resource
    private XlwClientFeign xlwClientFeign;
    @Resource
    private HistoryService historyService;
    @Resource
    private EventDetailMapper eventDetailMapper;
    @Value("${qxsd.xlw.images}")
    private String xlwImagePath;
    @Resource
    private ISdgkApiService sdgkApiService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @GetMapping("/get")
    @Operation(summary = "获得事件详情")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    public CommonResult<EventDetailRespVO> getEventDetail(@RequestParam("id") String id) {
        EventDetailDO eventDetail = eventDetailService.getEventDetail(id);
        return success(EventDetailDO.convert2VO(eventDetail,xlwImagePath));
    }

    @PostMapping("/page")
    @Operation(summary = "获得事件详情分页")
    public CommonResult<PageResult<EventDetailRespVO>> getEventDetailPage(@Valid @RequestBody EventDetailPageReqVO pageReqVO) {
        // 调用eventDetailService的getEventDetailPage方法，传入pageReqVO参数，获得PageResult对象
        PageResult pageResult = eventDetailService.getEventDetailPage(pageReqVO);
        // 将PageResult对象中的list属性转换为EventDetailRespVO对象，并设置xlwImagePath属性
        pageResult.setList(EventDetailDO.convert2VO(pageResult.getList(),xlwImagePath));
        // 返回成功结果，包含PageResult对象
        return success(pageResult);
    }

    @PostMapping("/dispelEvent")
    @Operation(summary = "事件消除")
    public CommonResult<String> dispelEvent(@Valid @RequestBody EventDetailDispelReqVO reqVO){
        eventDetailService.dispelEvent(reqVO.getId(),reqVO.getDispelCause(),reqVO.getProcessingOperationsName());
        return CommonResult.success("操作成功");
    }

    @GetMapping("/report")
    @Operation(summary = "事件上报给隧道管控")
    public CommonResult<String> reportEvent(@RequestParam("id") String id,@RequestParam(value = "processingOperationsName",required = false) String processingOperationsName){
        EventDetailDO eventDetail = eventDetailService.getEventDetail(id);
        if (eventDetail==null){
            throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),"事件不存在。");
        }
        if (eventDetail.getEventSource()== XlwConstants.EVENT_SOURCE_SDGK){
            throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),"该事件来源属于隧道管控，不需要上报。");
        }
        eventDetail.setProcessingType(1);
        eventDetail.setProcessingOperationsName(processingOperationsName);
        eventDetail.setProcessingTime(new Date());
        eventDetailService.reporEventToSdgk(eventDetail);
        return CommonResult.success("操作成功");
    }

    @GetMapping("/syncEventDetail")
    @Operation(summary = "同步指定时间内的事件")
    public CommonResult<String> syncEventDetail(@RequestParam("startDateTime") Date startDateTime,@RequestParam("endDateTime") Date endDateTime){
        eventGateway.syncEventDetailList(startDateTime,endDateTime);
        return CommonResult.success("操作成功");
    }

    @GetMapping("/syncEventDetailByStr")
    @Operation(summary = "同步指定时间内的事件")
    public CommonResult<String> syncEventDetailByStr(@RequestParam("startDateTime") String startDateTime,@RequestParam("endDateTime") String endDateTime) {
        xlwEventMapper.syncEventDetailListV2(startDateTime,endDateTime);
        return CommonResult.success("操作成功");
    }


    @PostMapping("/getBayonetPicture")
    @Operation(summary = "获取卡口图片")
    public CommonResult<PageResult<XlwBayonetPictureDTO>> getBayonetPicture(@RequestBody XlwBayonetPictureSearchDTO searchDTO){
        XlwResultData<XlwPageDTO<XlwBayonetPictureDTO>> resultData = xlwClientFeign.getBayonetPicture(searchDTO);
        PageResult<XlwBayonetPictureDTO> pageResult = new PageResult<>();
        XlwPageDTO<XlwBayonetPictureDTO> xlwPageDTO = resultData.getData();
        pageResult.setList(xlwPageDTO.getRows());
        pageResult.setTotal(xlwPageDTO.getTotal());
        return CommonResult.success(pageResult);
    }

    @GetMapping("/eventHis")
    @Operation(summary = "获取事件的历史数据")
    public CommonResult<EventHisRespVO> getEventHisDetail(@RequestParam("eventId") String eventId){
        return CommonResult.success(eventDetailService.getEventHisDetail(eventId));
    }

    @GetMapping("/saveEventHis")
    public CommonResult<String> saveEventHis(@RequestParam String eventId){
        Arrays.stream(eventId.split(",")).forEach(id->{
            EventDetailDO eventDetailDO = eventDetailMapper.selectById(id);
            historyService.saveEventHistoryData(eventDetailDO);
        });
        return success("操作成功");
    }

    @GetMapping("/sdgkAlarm")
    @Operation(summary = "获取隧道管控告警事件详情")
    public CommonResult<SdgkEventAlarmDTO> getSdgkAlarm(@RequestParam String alarmId){
        SdgkEventAlarmDTO result = sdgkApiService.alarmDetail(alarmId);
        return success(result);
    }

    @GetMapping("/sdgkAlarm/resource")
    @Operation(summary = "获取隧道管控告警事件媒体资源")
    public CommonResult<SdgkEventAlarmResourceDTO> getSdgkAlarmResource(@RequestParam String alarmId){
        SdgkEventAlarmResourceDTO result = sdgkApiService.alarmResource(alarmId);
        return success(result);
    }

    @GetMapping("/alarm")
    @Operation(summary = "获取事件告警的弹窗需要数据")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    public CommonResult<EventDetailAlarmVO> alarm(@RequestParam("id") String id){
        EventDetailAlarmVO vo = new EventDetailAlarmVO();
        long startTimeDetail = System.currentTimeMillis();
        vo.setEventDetailRespVO(getEventDetail(id).getData());
        log.info("告警的弹窗,详情:{},耗时:{}毫秒",id,System.currentTimeMillis() - startTimeDetail);
        long startTimeHis = System.currentTimeMillis();
        vo.setEventHisRespVO(getEventHisDetail(id).getData());
        // 这个页面不需要这个字段，这个字段太大，没必要加载
        vo.getEventHisRespVO().setHisVehicleInfo(null);
        log.info("告警的弹窗,历史:{},耗时:{}毫秒",id,System.currentTimeMillis() - startTimeHis);
        // 额外处理
        long startTimeOther = System.currentTimeMillis();
        if(CollectionUtils.isNotEmpty(vo.getEventDetailRespVO().getCarInfoList())){
            vo.getEventDetailRespVO().getCarInfoList().forEach(carInfo->{
                //危是否化品车辆，枚举：0否、1是
                carInfo.setIsDangerous(carInfo.getVehicleType()==0);
                //是否重点标记
                if(StringUtils.isNotEmpty(carInfo.getCarId())){
                    //取交集(当前重点标记的车辆)
                    String redisStr = stringRedisTemplate.opsForValue().get(RedisConstants.REDIS_FOCUS_VEHICLE_MARK_KEY + carInfo.getCarId());
                    if(StringUtils.isNotEmpty(redisStr) && redisStr.equals(carInfo.getCarId())){
                        carInfo.setIsFocusMark(true);
                    }
                }
                // 查询实时车流如果不存在说明已经驶出隧道，否则还在隧道内
                String realTimeVehicleJson = stringRedisTemplate.opsForValue().get(RedisConstants.REDIS_REAL_TIME_VEHICLE_KEY.concat(vo.getEventDetailRespVO().getTunnelId()));
                TunnelRealTimeVehicle realTimeVehicle =JSONObject.parseObject(realTimeVehicleJson, TunnelRealTimeVehicle.class);
                if(Objects.nonNull(realTimeVehicle) && CollectionUtils.isNotEmpty(realTimeVehicle.getVehicleInfoList())) {
                    realTimeVehicle.getVehicleInfoList().forEach(vehicleInfo -> {
                        if (carInfo.getCarId().equals(vehicleInfo.getCarId())) {
                            carInfo.setIsDriveTunnel(true);
                        }
                    });
                }
                EventHisDO.EventHisExpandInfo x = EventHisDO.getEventHisExpandInfo(vo.getEventHisRespVO().getExpandInfo(),carInfo.getCarPlate());
                carInfo.setInTunnelTimeStr(x.getVehicleInTunnelTime());
                carInfo.setCarImageUrl(x.getSmallSideImage());
                // 车辆还在隧道内
                if(carInfo.getIsDriveTunnel()){
                    if(StringUtils.isNotEmpty(x.getVehicleInTunnelTime())){
                        try {
                            Date date = DateUtil.parse(x.getVehicleInTunnelTime(),"yyyy-MM-dd HH:mm:ss");
                            long diffMinTime = ((System.currentTimeMillis() - date.getTime())/1000/60);
                            if(diffMinTime < 0){
                                diffMinTime = 0;
                            }
                            carInfo.setRetainedMinutesTime((int) diffMinTime);
                        } catch (Exception e) {
                            log.error("时间格式转换异常,his车辆入隧时间",e);
                        }
                    }

                }
                log.info("告警的弹窗,其他处理:{},耗时:{}毫秒",id,System.currentTimeMillis() - startTimeOther);
            });
        }
        return success(vo);
    }


    /**
     * 测试推送给前端的事件数据
     * @param eventId
     * @return
     */
    @GetMapping("/pushRealTimeEventData")
    public CommonResult pushRealTimeEventData(@RequestParam("tunnelId") String tunnelId,@RequestParam("eventId") String eventId){
        Arrays.stream(eventId.split(",")).forEach(id->{
            eventGateway.pushRealTimeEventData(tunnelId,id);
        });

        return success("操作成功");
    }

    /**
     * 测试保存切片视频，需要通过打印的日志作为参数进行保存
     * @return
     */
    @GetMapping("/videoPuller")
    public CommonResult videoPuller(@RequestParam("rtspUrl") String rtspUrl,@RequestParam("outputFile") String outputFile){
        historyGateway.videoPuller(rtspUrl, outputFile);
        return success("操作成功");
    }

}
