package com.artfess.device.base.manager.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.artfess.base.context.BaseContext;
import com.artfess.base.manager.impl.BaseManagerImpl;
import com.artfess.base.query.PageBean;
import com.artfess.base.query.PageList;
import com.artfess.base.query.QueryFilter;
import com.artfess.base.util.BeanUtils;
import com.artfess.base.util.DateUtils;
import com.artfess.device.base.config.MqConstant;
import com.artfess.device.base.dao.DeviceVideoBaseDao;
import com.artfess.device.base.dao.DeviceVideoPointExtendDao;
import com.artfess.device.base.manager.DeviceVideoBaseManager;
import com.artfess.device.base.manager.DeviceVideoPointManager;
import com.artfess.device.base.manager.DeviceVideoZoneManager;
import com.artfess.device.base.manager.DeviceWarnInfoManager;
import com.artfess.device.base.model.DeviceVideoBase;
import com.artfess.device.base.model.DeviceVideoPoint;
import com.artfess.device.base.model.DeviceVideoPointExtend;
import com.artfess.device.base.model.DeviceVideoZone;
import com.artfess.device.base.model.DeviceWarnInfo;
import com.artfess.device.base.vo.CollectVo;
import com.artfess.device.base.vo.DeviceWarnInfoVo;
import com.artfess.device.base.vo.HaiKangRequest;
import com.artfess.device.base.vo.HaiKangResult;
import com.artfess.device.base.vo.TreeCodeRespVo;
import com.artfess.rocketmq.producer.RocketMQProducer;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.hikvision.artemis.sdk.ArtemisHttpUtil;
import com.hikvision.artemis.sdk.config.ArtemisConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 视频目录基础信息表（DEVICE_VIDEO_BASE） 服务实现类
 *
 * @author min.wu
 * @company 阿特菲斯信息技术有限公司
 * @since 2022-08-19
 */
@Slf4j
@Service
public class DeviceVideoBaseManagerImpl extends BaseManagerImpl<DeviceVideoBaseDao, DeviceVideoBase> implements DeviceVideoBaseManager {

    @Autowired
    private DeviceVideoZoneManager videoZoneManager;

    @Autowired
    private DeviceVideoPointManager videoPointManager;

    @Autowired
    private DeviceWarnInfoManager warnInfoManager;

    @Resource
    private BaseContext baseContext;

    @Resource
    private DeviceVideoPointExtendDao deviceVideoPointExtendDao;

    @Autowired
    private RocketMQProducer rocketMQUtils;

    /**
     * STEP1：设置平台参数，根据实际情况,设置host appkey appsecret 三个参数.
     */
    static {
        ArtemisConfig.host = "183.230.114.212:10220";// 平台门户/nginx的IP和端口（必须使用https协议，https端口默认为443）
        ArtemisConfig.appKey = "27900477"; // 秘钥appkey
        ArtemisConfig.appSecret = "OTeHSUxGKwFMSKEPdrll";// 秘钥appSecret
    }

    /**
     * STEP2：设置OpenAPI接口的上下文
     */
    final String ARTEMIS_PATH = "/artemis";

    public List<DeviceVideoBase> getAllTreeCode(HaiKangRequest getAllTreeCodeRequest) {
        String getAllTreeCodeDataApi = ARTEMIS_PATH + "/api/resource/v1/unit/getAllTreeCode";
        Map<String, String> path = new HashMap<String, String>(2) {
            {
                put("https://", getAllTreeCodeDataApi);
            }
        };
        String body = JSON.toJSONString(getAllTreeCodeRequest);
        String result = ArtemisHttpUtil.doPostStringArtemis(path, body, null, null, "application/json");
        log.info("海康目录响应数据：{}", result);
        Assert.hasText(result, "获取海康资源目录失败");
        HaiKangResult haiKangResult = JSONObject.parseObject(result, HaiKangResult.class);
        if ("0".equals(haiKangResult.getCode())) {
            List<TreeCodeRespVo> resourceList = JSONArray.parseArray(haiKangResult.getData().getString("list"), TreeCodeRespVo.class);
            List<DeviceVideoBase> list = Lists.newArrayList();
            resourceList.forEach(treeCodeRespVo -> {
                DeviceVideoBase videoBase = new DeviceVideoBase();
                videoBase.setCode(treeCodeRespVo.getTreeCode());
                videoBase.setName(treeCodeRespVo.getTreeName());
                videoBase.setPlatform("HK");
                list.add(videoBase);
            });
            return list;
        } else {
            throw new IllegalArgumentException("获取海康资源目录失败");
        }
    }


    //分页获取区域列表
    public void regions(HaiKangRequest haiKangRequest) {
        String regionsDataApi = ARTEMIS_PATH + "/api/resource/v1/regions";
        Map<String, String> path = new HashMap<String, String>(2) {
            {
                put("https://", regionsDataApi);
            }
        };

        haiKangRequest.getTreeCodes().forEach(treeCode -> {
            haiKangRequest.setTreeCode(treeCode);
            haiKangRequest.setPageSize(2000);
            String body = JSON.toJSONString(haiKangRequest);
            String result = ArtemisHttpUtil.doPostStringArtemis(path, body, null, null, "application/json");
            log.info("海康区域信息响应数据：{}", result);
            Assert.hasText(result, "获取海康区域信息失败");
            HaiKangResult haiKangResult = JSONObject.parseObject(result, HaiKangResult.class);
            QueryWrapper<DeviceVideoZone> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("base_code_", haiKangRequest.getTreeCode());
            videoZoneManager.getBaseMapper().delete(queryWrapper);

            if ("0".equals(haiKangResult.getCode())) {
                List<JSONObject> resourceList = JSONArray.parseArray(haiKangResult.getData().getString("list"), JSONObject.class);
                resourceList.stream().forEach(item -> {
                    DeviceVideoZone zone = new DeviceVideoZone();
                    zone.setCode(item.getString("indexCode"));
                    zone.setPlatform("HK");
                    zone.setName(item.getString("name"));
                    zone.setBaseCode(item.getString("treeCode"));
                    zone.setParentId(item.getString("parentIndexCode"));
                    zone.setId(zone.getCode());
                    String userId = baseContext.getCurrentUserId();
                    String orgId = baseContext.getCurrentOrgId();
                    zone.setCreateTime(LocalDateTime.now());
                    zone.setUpdateTime(LocalDateTime.now());
                    zone.setCreateBy(userId);
                    zone.setCreateOrgId(orgId);
                    videoZoneManager.saveTreeAndId(zone);
                });
            } else {
                throw new IllegalArgumentException("获取海康资源目录失败");
            }
        });
    }


    /**
     * 分页获取监控点资源
     *
     * @param camerasRequest
     * @return
     */
    public List<DeviceVideoPoint> cameras(HaiKangRequest camerasRequest) {
        String camerasDataApi = ARTEMIS_PATH + "/api/resource/v1/cameras";
        Map<String, String> path = new HashMap<String, String>(2) {
            {
                put("https://", camerasDataApi);
            }
        };
        List<String> codeList = this.baseMapper.findCodeByPlatform("HK");
        List<DeviceVideoPoint> list = Lists.newArrayList();
        if(codeList!=null && codeList.size()>0){
            for(String baseCode :codeList ){
                camerasRequest.setTreeCode(baseCode);
                String body=JSON.toJSONString(camerasRequest);
                String result =ArtemisHttpUtil.doPostStringArtemis(path,body,null,null,"application/json");
                log.info("海康监控点响应数据：{}", result);
                Assert.hasText(result, "获取海康监控点失败");
                HaiKangResult haiKangResult = JSONObject.parseObject(result, HaiKangResult.class);
                if ("0".equals(haiKangResult.getCode())) {
                    List<JSONObject> resourceList = JSONArray.parseArray(haiKangResult.getData().getString("list"), JSONObject.class);
                    List<DeviceWarnInfo> warnInfoList = new ArrayList<>();
                    resourceList.forEach(jsonObject -> {
                        DeviceVideoPoint res = new DeviceVideoPoint();
                        res.setCatalogCode(baseCode);
                        res.setZoneCode(jsonObject.getString("unitIndexCode"));
                        res.setCode(jsonObject.getString("cameraIndexCode"));
                        res.setPlatform("HK");
                        res.setName(jsonObject.getString("name"));
                        res.setLgtd(jsonObject.getString("longitude"));
                        res.setLttd(jsonObject.getString("latitude"));
                        res.setAddress(jsonObject.getString("installPlace"));
                        res.setStatus(jsonObject.getString("status"));
                        res.setAisle(jsonObject.getString("chanNum"));
                        res.setId(res.getCode());
                        String userId = baseContext.getCurrentUserId();
                        String orgId = baseContext.getCurrentOrgId();
                        res.setCreateTime(LocalDateTime.now());
                        res.setUpdateTime(LocalDateTime.now());
                        res.setCreateBy(userId);
                        res.setCreateOrgId(orgId);
                        list.add(res);
                        //判断不在线情况
                        String code = String.valueOf(jsonObject.getString("cameraIndexCode"));
                        if(jsonObject.getString("status")==null || !jsonObject.getString("status").equals("1")){
                            videoPointManager.updateVideoStatus(code,"2");
                            //获取该设备的最新一条报警数据，判断其有没有处理，如果没有处理就不增加报警数据，如果处理了就新增报警数据
                            DeviceWarnInfo warnInfo = warnInfoManager.getNewWarnInfo(code,"1");
                            if(warnInfo == null || (warnInfo!=null && warnInfo.getHandleStatus()==1)){
                                warnInfo = new DeviceWarnInfo();
                                warnInfo.setDeviceCode(code);
                                warnInfo.setWarnName("视频设备【"+jsonObject.getString("name")+"】离线告警！");
                                warnInfo.setWarnType("1");
                                warnInfo.setDeviceType("5");
                                warnInfo.setWarnReason("视频设备【"+jsonObject.getString("name")+"】离线，可能发生故障！");
                                warnInfo.setWarnTime(res.getCreateTime());
                                warnInfo.setCreateTime(LocalDateTime.now());
                                warnInfo.setHandleStatus(0);
                                warnInfoList.add(warnInfo);
                                //上报事件中心
                                DeviceWarnInfoVo deviceWarnInfoVo = new DeviceWarnInfoVo();
                                deviceWarnInfoVo.setDevName(jsonObject.getString("name"));
                                deviceWarnInfoVo.setDevCode(warnInfo.getDeviceCode());
                                deviceWarnInfoVo.setEventSrcId(warnInfo.getId());
                                deviceWarnInfoVo.setEventTitle(warnInfo.getWarnName());
                                deviceWarnInfoVo.setEventTime(DateUtils.now());
                                deviceWarnInfoVo.setEventSubClass(warnInfo.getDeviceType());
                                deviceWarnInfoVo.setEventDesc(warnInfo.getWarnReason());
                                deviceWarnInfoVo.setEventType(Integer.valueOf(warnInfo.getWarnType()));
                                deviceWarnInfoVo.setEventAddr(jsonObject.getString("installPlace"));
                                if(!org.springframework.util.StringUtils.isEmpty(jsonObject.getString("latitude"))){
                                    deviceWarnInfoVo.setEventLat(new BigDecimal(jsonObject.getString("latitude")));
                                }
                                if(!org.springframework.util.StringUtils.isEmpty(jsonObject.getString("longitude"))){
                                    deviceWarnInfoVo.setEventLng(new BigDecimal(jsonObject.getString("longitude")));
                                }

                                DeviceVideoPointExtend videoPointExtend = deviceVideoPointExtendDao.findVideoExtendByCode(warnInfo.getDeviceCode());
                                if(videoPointExtend!=null){
                                    deviceWarnInfoVo.setRegionCode(videoPointExtend.getAreaCode());
                                    deviceWarnInfoVo.setRegionName(videoPointExtend.getAreaName());
                                }
                                //上传报警给MQ
                                String warnInfoString = JSON.toJSONString(deviceWarnInfoVo);
                                try{
                                    rocketMQUtils.send(MqConstant.SEND_STATUS_TOPIC, warnInfoString);
                                }catch (Exception e) {
                                    log.error("发送失败:{}", e);
                                }
                            }
                        }
                        if(jsonObject.getString("status").equals("1")){
                            videoPointManager.updateVideoStatus(code,"1");
                        }
                    });
                    if(warnInfoList!=null && warnInfoList.size()>0){
                        warnInfoManager.saveBatch(warnInfoList);
                    }
                }else{
                    continue;
                }
            }
        }

        return list;
    }



    /**
     * 获取监控点预览取流URL
     */
    @Override
    public String hkPreviewURLs(String code,String module) {
        String previewURLsDataApi = ARTEMIS_PATH + "/api/video/v1/cameras/previewURLs";
        Map<String, String> path = new HashMap<String, String>(2) {
            {
                put("https://", previewURLsDataApi);
            }
        };
        HaiKangRequest previewURLsRequest = new HaiKangRequest();
        previewURLsRequest.setProtocol(module);
        previewURLsRequest.setCameraIndexCode(code);
        previewURLsRequest.setStreamType(0);
        previewURLsRequest.setTransmode(0);
        String body = JSON.toJSONString(previewURLsRequest);
        String result = ArtemisHttpUtil.doPostStringArtemis(path, body, null, null, "application/json");

        Assert.hasText(result, "获取视频流地址失败");
        HaiKangResult haiKangResult = JSONObject.parseObject(result, HaiKangResult.class);
        if ("0".equals(haiKangResult.getCode())) {
            String url = haiKangResult.getData().getString("url");
            return url;
        } else {
            throw new IllegalArgumentException("获取视频流地址失败");
        }
    }


    @Override
    public PageList<DeviceVideoPoint> findByPage(QueryFilter<DeviceVideoBase> queryFilter) {
        PageBean pageBean = queryFilter.getPageBean();
        IPage<DeviceVideoBase> page = new Page<>(pageBean.getPage(), pageBean.getPageSize());

        QueryWrapper<DeviceVideoBase> queryWrapper = convert2Wrapper(queryFilter,DeviceVideoBase.class);
        queryWrapper.orderByDesc("b.CREATE_TIME_");

        IPage<DeviceVideoPoint> pageList = this.baseMapper.findByPage(page, queryWrapper);
        return new PageList<>(pageList);
    }


    @Override
    public List<DeviceVideoZone> getTree(CollectVo t) {
        QueryWrapper<DeviceVideoZone> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(t.getZoneCode())) {
            queryWrapper.eq("base_code_", t.getZoneCode());
        }
        List<DeviceVideoZone> baseList = videoZoneManager.getBaseMapper().selectList(queryWrapper);
        List<DeviceVideoZone> zoneList = BeanUtils.listToTree(baseList);
        return zoneList;
    }

    @Override
    public List<DeviceVideoBase> getCataLogBase() {
        QueryWrapper<DeviceVideoBase> queryWrapper = new QueryWrapper<>();
        List<DeviceVideoBase> baseList = this.baseMapper.selectList(queryWrapper);
        return baseList;
    }

    @Override
    public List<DeviceVideoPoint> findByZoneCode(QueryFilter<DeviceVideoBase> queryFilter) {
        return this.baseMapper.findByZoneCode(queryFilter.getParams());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void asycCataLog() {
       this.baseMapper.delete(null);
        HaiKangRequest request = new HaiKangRequest();
        List<DeviceVideoBase> baseList = this.getAllTreeCode(request);
        DeviceVideoBase zgVideoBase = new DeviceVideoBase();
        zgVideoBase.setCode("zg001");
        zgVideoBase.setName("紫光华智视频平台");
        zgVideoBase.setPlatform("ZG");
        zgVideoBase.setSn(baseList.size()+1);
        baseList.add(zgVideoBase);
        this.saveBatch(baseList);
        //同步海康平台的视频目录
        request.setPageSize(1);
        List<String> treeCodes = Lists.newArrayList();

        baseList.forEach(DeviceVideoBase -> {
            if(DeviceVideoBase.getPlatform().equals("HK")){
                treeCodes.add(DeviceVideoBase.getCode());
            }

        });
        request.setTreeCodes(treeCodes);
        this.regions(request);

        //同步紫光华智平台的视频目录
        QueryWrapper<DeviceVideoZone> zoneWrapper = new QueryWrapper<>();
        zoneWrapper.eq("platform_", "ZG");
        this.videoZoneManager.remove(zoneWrapper);
        videoPointManager.asycZGZone(false);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void asycCataLogZone(HaiKangRequest haiKangRequest) {
        QueryWrapper<DeviceVideoZone> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("base_code_", haiKangRequest.getTreeCode());
        videoZoneManager.getBaseMapper().delete(queryWrapper);
        List<String> treeCodes = Lists.newArrayList();
        treeCodes.add(haiKangRequest.getTreeCode());
        haiKangRequest.setTreeCodes(treeCodes);
        this.regions(haiKangRequest);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void asycZoneRes(HaiKangRequest haiKangRequest) {
        //videoPointManager.deleteZoneRes(haiKangRequest.getRegionIndexCode());
        QueryWrapper<DeviceVideoPoint> queryWrapper =new QueryWrapper<>();
       // queryWrapper.eq("platform_", "ZG");
        videoPointManager.getBaseMapper().delete(queryWrapper);

        //获取海康的点位
        List<DeviceVideoPoint> hkResList = this.cameras(haiKangRequest);
        //获取华智的点位
        List<DeviceVideoPoint> zgResList = videoPointManager.asycZGcameras(false);
        List<DeviceVideoPoint> resList =Lists.newArrayList();
        resList.addAll(hkResList);
        resList.addAll(zgResList);

        videoPointManager.saveBatch(resList);
    }


    @Override
    public List<DeviceVideoZone> getAllTree(CollectVo t) {
        QueryWrapper<DeviceVideoZone> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(t.getZoneCode())) {
            queryWrapper.eq("base_code_", t.getZoneCode());
        }
        List<DeviceVideoZone> baseList = videoZoneManager.getBaseMapper().selectList(queryWrapper);


        List<DeviceVideoZone> DeviceVideoPoint = this.baseMapper.findByRes();
        DeviceVideoPoint.forEach(videoPoint -> {
            videoPoint.setType("2");
        });

        Map<String, List<DeviceVideoZone>> resMap = DeviceVideoPoint.stream().collect(Collectors.groupingBy(DeviceVideoZone::getParentId));
        baseList.forEach(videoZone -> {
            videoZone.setType("1");
            if (resMap.containsKey(videoZone.getCode())) {
                videoZone.setChildren(resMap.get(videoZone.getCode()));
            }

        });
        List<DeviceVideoZone> zoneList = BeanUtils.listToTree(baseList);

        return zoneList;
    }


}
