package com.dji.sample.manage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dji.sample.common.smsp.CallSmsp;
import com.dji.sample.common.util.DesUtil;
import com.dji.sample.configuration.CustomConfiguration;
import com.dji.sample.manage.dao.IManageDeviceLivestreamUrlMapper;
import com.dji.sample.manage.dao.IUserMapper;
import com.dji.sample.manage.log.annotation.Log;
import com.dji.sample.manage.log.enums.BusinessType;
import com.dji.sample.manage.model.dto.ManageDeviceLivestreamUrlDTO;
import com.dji.sample.manage.model.dto.RtmpUrlDTO;
import com.dji.sample.manage.model.dto.UpstreamLivestreamUrlDTO;
import com.dji.sample.manage.model.entity.ManageDeviceLivestreamUrlEntity;
import com.dji.sample.manage.model.entity.UserEntity;
import com.dji.sample.manage.model.enums.LiveUrlTypeEnum;
import com.dji.sample.manage.model.enums.UserTypeEnum;
import com.dji.sample.manage.service.IManageDeviceLivestreamUrlService;
import com.dji.sdk.cloudapi.device.DeviceSubTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
@Transactional
@Slf4j
public class ManageDeviceLivestreamUrlServiceImpl implements IManageDeviceLivestreamUrlService {

    @Autowired
    private IUserMapper userMapper;

    @Autowired
    private IManageDeviceLivestreamUrlMapper mapper;



    @Override
    public ManageDeviceLivestreamUrlDTO getUrl(ManageDeviceLivestreamUrlDTO deviceLivestreamUrlDTO,String protocal) {


        QueryWrapper<UserEntity> userWrapper = new QueryWrapper<>();
        userWrapper.lambda().eq(UserEntity::getUserType, UserTypeEnum.API.getVal()).eq(UserEntity::getClientId, CustomConfiguration.clientId);
        UserEntity userEntity = userMapper.selectOne(userWrapper);
        if (userEntity == null) {
            log.info("接口用户不存在，ClientId:" + CustomConfiguration.clientId);
            throw new RuntimeException ("接口用户不存在,无法获取流媒体地址信息");
        }
        //密码解密
        String password = DesUtil.getDecryptData(userEntity.getPassword(),userEntity.getSalt());
        //获取token
        Map<String,String> tokenMap = CallSmsp.getSmspToken(userEntity.getUsername(),password,protocal);
        if(tokenMap.get("Token") == null) {
            log.info("调用流媒体服务，获取token失败");
        }

        //获取rtmp地址
        RtmpUrlDTO rtmpUrlDTO = CallSmsp.getRtmp(tokenMap.get("Token"),deviceLivestreamUrlDTO.getDeviceSn(),protocal);
        ManageDeviceLivestreamUrlDTO rtmpDto = new ManageDeviceLivestreamUrlDTO();

        //获取数据库中deviceSn对应的url信息
        QueryWrapper<ManageDeviceLivestreamUrlEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(ManageDeviceLivestreamUrlEntity::getDeviceSn,deviceLivestreamUrlDTO.getDeviceSn())
                .eq(ManageDeviceLivestreamUrlEntity::getWorkspaceId,deviceLivestreamUrlDTO.getWorkspaceId());
        List<ManageDeviceLivestreamUrlEntity> urlListFromDB = mapper.selectList(wrapper);

        if(urlListFromDB.size() == 0 && rtmpUrlDTO.getMessage() != null ){
            if(tokenMap.get("message") != null) {
                throw new RuntimeException (tokenMap.get("message"));
            }
            if(rtmpUrlDTO.getMessage() != null) {
                throw new RuntimeException (rtmpUrlDTO.getMessage());
            }
            throw new RuntimeException ("获取推流拉流地址异常，请联系技术人员确认！");
        }
        List<ManageDeviceLivestreamUrlDTO> rtmpList =  new ArrayList<>();
        if (rtmpUrlDTO.getList().size() > 0) {
            rtmpList = rtmpUrlDTO.getList();
        }
        List<Integer> urlL = urlListFromDB.stream()
                .map(ManageDeviceLivestreamUrlEntity::getChannelId)
                .collect(Collectors.toList());
        //筛选数据库中payloadIndex相同的记录
        List<ManageDeviceLivestreamUrlEntity> filterIndexList =
                urlListFromDB.stream().filter(channelData -> deviceLivestreamUrlDTO.getPayloadIndex().equals(channelData.getPayloadIndex()))
                .collect(Collectors.toList());
        if (filterIndexList.size() > 0) {
            //筛选数据库中channelId相同的记录
            List<ManageDeviceLivestreamUrlDTO> channelList =
                    rtmpList.stream().filter(channelData -> filterIndexList.get(0).getChannelId().equals(channelData.getChannelId()))
                    .collect(Collectors.toList());
            if (channelList.size() > 0) {
                update(filterIndexList,channelList);
                rtmpDto.setRtmpUrl(channelList.get(0).getRtmpUrl());
                rtmpDto.setWebRtcUrl(channelList.get(0).getWebRtcUrl());
            } else {
                if(rtmpList.size() > 0) {
                    //筛选数据库中不存在的记录
                    channelList = rtmpList.stream().filter(channelData -> !urlL.contains(channelData.getChannelId()))
                            .collect(Collectors.toList());
                    update(filterIndexList,channelList);
                    rtmpDto.setRtmpUrl(channelList.get(0).getRtmpUrl());
                    rtmpDto.setWebRtcUrl(channelList.get(0).getWebRtcUrl());
                } else {
                    for(ManageDeviceLivestreamUrlEntity url : filterIndexList) {
                        if (url.getUrlType().equals(LiveUrlTypeEnum.RTMP.getVal())) {
                            rtmpDto.setRtmpUrl(url.getUrl());
                        } else if(url.getUrlType().equals(LiveUrlTypeEnum.WEBRTC.getVal())) {
                            rtmpDto.setWebRtcUrl(url.getUrl());
                        }
                    }
                }
            }
        } else {
            //数据库中不存在
            List<ManageDeviceLivestreamUrlDTO> channelList =
                    rtmpList.stream().filter(channelData -> !urlL.contains(channelData.getChannelId()))
                            .collect(Collectors.toList());
            ManageDeviceLivestreamUrlEntity urlEntity = new ManageDeviceLivestreamUrlEntity();
            if(channelList.size() > 0) {
                urlEntity.setDeviceSn(deviceLivestreamUrlDTO.getDeviceSn());
                urlEntity.setWorkspaceId(deviceLivestreamUrlDTO.getWorkspaceId());
                urlEntity.setPayload(deviceLivestreamUrlDTO.getPayload());
                urlEntity.setPayloadIndex(deviceLivestreamUrlDTO.getPayloadIndex());
                //存库Rtmp
                urlEntity.setSubType(DeviceSubTypeEnum.ONE.getSubType());
                urlEntity.setUrlType(LiveUrlTypeEnum.RTMP.getVal());
                urlEntity.setChannelId(channelList.get(0).getChannelId());
                urlEntity.setUrl(channelList.get(0).getRtmpUrl());
                mapper.insert(urlEntity);
                //存库WEBRTC
                urlEntity.setId(null);
                urlEntity.setSubType(DeviceSubTypeEnum.TWO.getSubType());
                urlEntity.setUrlType(LiveUrlTypeEnum.WEBRTC.getVal());
                urlEntity.setUrl(channelList.get(0).getWebRtcUrl());
                mapper.insert(urlEntity);
                rtmpDto.setRtmpUrl(channelList.get(0).getRtmpUrl());
                rtmpDto.setWebRtcUrl(channelList.get(0).getWebRtcUrl());
            } else {
                throw new RuntimeException("没有获取到可以使用的推流和拉流地址");
            }
        }
        return rtmpDto;
    }

    @Override
    public List<UpstreamLivestreamUrlDTO> selWebRtc(String payload, String deviceSn,String workspaceId) {
        List<UpstreamLivestreamUrlDTO> resultList = new ArrayList<>();
        LambdaQueryWrapper<ManageDeviceLivestreamUrlEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ManageDeviceLivestreamUrlEntity::getUrlType,LiveUrlTypeEnum.WEBRTC.getVal())
                .eq(null!= payload,ManageDeviceLivestreamUrlEntity::getPayloadIndex,payload)
                .eq(null!= workspaceId,ManageDeviceLivestreamUrlEntity::getWorkspaceId,workspaceId)
                .eq(null!= deviceSn,ManageDeviceLivestreamUrlEntity::getDeviceSn,deviceSn);
        List<ManageDeviceLivestreamUrlEntity> result = mapper.selectList(wrapper);
        if(result.size() > 0 ) {
            for(ManageDeviceLivestreamUrlEntity entity :result) {
                UpstreamLivestreamUrlDTO upstreamLivestreamUrlDTO = new UpstreamLivestreamUrlDTO();
                upstreamLivestreamUrlDTO.setWorkspaceId(entity.getWorkspaceId());
                upstreamLivestreamUrlDTO.setDeviceSn(entity.getDeviceSn());
                upstreamLivestreamUrlDTO.setUrl(entity.getUrl());
                upstreamLivestreamUrlDTO.setPayload(entity.getPayloadIndex());
                resultList.add(upstreamLivestreamUrlDTO);
            }
        }
        return resultList;
    }

    private void update(List<ManageDeviceLivestreamUrlEntity> entitys,List<ManageDeviceLivestreamUrlDTO> dtos) {
        for(ManageDeviceLivestreamUrlEntity url : entitys) {
            url.setChannelId(dtos.get(0).getChannelId());
            if (url.getUrlType().equals(LiveUrlTypeEnum.RTMP.getVal())) {
                url.setUrl(dtos.get(0).getRtmpUrl());
                mapper.updateById(url);
            } else if(url.getUrlType().equals(LiveUrlTypeEnum.WEBRTC.getVal())) {
                url.setUrl(dtos.get(0).getWebRtcUrl());
                mapper.updateById(url);
            }
        }
    }


}
