package com.sptg.estate.biz.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.sptg.common.core.entity.DispatchTask;
import com.sptg.common.core.util.JsonUtils;
import com.sptg.device.api.feigns.DeviceFeign;
import com.sptg.estate.api.entity.VideoCallAccount;
import com.sptg.estate.biz.mapper.VideoCallAccountMapper;
import com.sptg.estate.biz.service.VideoCallAccountServiceInterface;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.stream.Collectors;

/**
 * title: VideoCallAccountServiceImpl
 * package: com.sptg.estate.biz.security.impl
 * description: 视频呼叫账号-CURD业务实现
 *
 *                  
 *                
 */
@Service
@RequiredArgsConstructor
public class VideoCallAccountServiceImpl extends ServiceImpl<VideoCallAccountMapper,VideoCallAccount> implements VideoCallAccountServiceInterface {

    private String talkBackServerAddress = "http://114.55.106.95:8666";

    private String callGroupPrefix = "0000019627";
    
    private String accessToken = "b8ac10c5bc73385544d28840babcd5e8d6a1475cf3aaa88a333766b7";

    @Qualifier(value = "restTemplate")
    private final RestTemplate restTemplate;
    private final DeviceFeign deviceFeign;

    @Override
    public VideoCallAccount createAccount(Long userId, Long roomId) {
        VideoCallAccount account = this.createAccount(userId);
        //  呼叫组Id
        String groupId = this.callGroupPrefix + roomId;
        account.setUserId(userId);
        account.setRoomId(roomId);
        account.setCallGroupId(groupId);
        //  获取该呼叫组内的所有账号
        List<String> idList = this.selectAccountIdListByGroupId(groupId);
        idList.add(account.getAccountId());
        this.syncCallGroup(account.getCallGroupId(),idList);
        return account;
    }

    /**
     * 同步呼叫组
     * @param groupId 呼叫组Id
     * @param idList 对讲账号Id列表
     */
    private void syncCallGroup(String groupId,List<String> idList){
        HttpHeaders headers = new HttpHeaders();
        headers.add("Accept", MediaType.APPLICATION_JSON_UTF8.toString());
        //  请求参数
        Map<String,Object> parameterMap = new HashMap<>(3);
        parameterMap.put("access_token",this.accessToken);
        parameterMap.put("operation","PUT");
        Map<String,Object> dataMap = new HashMap<>(1);
        dataMap.put(groupId,idList);
        parameterMap.put("data",dataMap);
        String url = this.talkBackServerAddress + "/dmvphone/server/ring_group";
        Map map = this.sendRequest(url,parameterMap,headers);

        Assert.notNull(map,"同步呼叫组接口异常");
        int code = (int)map.get("ret");
        Assert.isTrue(0 == code,map.get("msg").toString());
    }

    /**
     * 调用西莫接口创建视频对讲账号
     * @param id 账号Id
     * @return VideoCallAccount
     */
    @Override
    public VideoCallAccount createAccount(Long id){
        //  调用西莫接口申请账号
        HttpHeaders headers = new HttpHeaders();
        headers.add("Accept", MediaType.APPLICATION_JSON_UTF8.toString());
        //  请求参数
        Map<String,Object> parameterMap = new HashMap<>(3);
        parameterMap.put("access_token",this.accessToken);
        parameterMap.put("operation","POST");
        Map<String,Object> dataMap = new HashMap<>(1);
        dataMap.put("account_list",new long[]{ id });
        parameterMap.put("data",dataMap);
        //  请求路径
        String url = this.talkBackServerAddress + "/dmvphone/server/voip_account";
        Map resultMap = this.sendRequest(url,parameterMap,headers);
        Assert.notNull(resultMap,"申请对讲账号返回数据格式异常");
        int code = (int)resultMap.get("ret");
        Assert.isTrue(0 == code,resultMap.get("msg").toString());
        //  得到返回值
        Map resultData = (Map)resultMap.get("data");
        Assert.notNull(dataMap,"申请对讲账号返回数据格式异常");
        Map map = (Map)resultData.get(id.toString());
        VideoCallAccount account = new VideoCallAccount();
        account.setAccountId((String) map.get("voip_account"));
        account.setAccountPwd((String) map.get("voip_password"));
        return account;
    }

    /**
     * 根据呼叫组Id 获取账号Id列表
     * @param groupId 呼叫组Id
     * @return List<String>
     */
    private List<String> selectAccountIdListByGroupId(String groupId){
        Wrapper<VideoCallAccount> wrapper = new EntityWrapper<>();
        wrapper.eq("call_group_id",groupId);
        wrapper.notIn("status",-1);
        return this.selectList(wrapper).stream().map(VideoCallAccount::getAccountId).collect(Collectors.toList());
    }

    @Override
    public boolean insert(VideoCallAccount entity) {
        entity.setStatus(0);
        Date nowTime = new Date();
        entity.setCreateTime(nowTime);
        entity.setLastModifyTime(nowTime);
        return super.insert(entity);
    }

    @Override
    public void pushCallAccount(VideoCallAccount account) {
        DispatchTask task = new DispatchTask();
        task.setXqId(account.getXqId());
        task.setUnitId(account.getUnitId());
        task.setData(account);
        this.deviceFeign.pushCallAccount(task);
    }

    @Async
    @Override
    public void deleteAccountByUserId(Long userId) {
        Wrapper<VideoCallAccount> wrapper = new EntityWrapper<>();
        wrapper.eq("user_id",userId);
        wrapper.notIn("status",-1);
        VideoCallAccount account = this.selectOne(wrapper);
        //  删除账号
        if (null != account){
            account.setStatus(-1);
            if (this.updateById(account)) {
                //  同步呼叫组
                if (account.getAccountType() == 1) {
                    //  获取该呼叫组内的所有账号
                    List<String> idList = this.selectAccountIdListByGroupId(account.getCallGroupId());
                    this.syncCallGroup(account.getCallGroupId(), idList);
                }
            }
        }
    }

    @Async
    @Override
    public void deleteAccountByRoomId(Long roomId) {
        //  删除该房间内的所有视频对讲账号
        Wrapper<VideoCallAccount> wrapper = new EntityWrapper<>();
        wrapper.eq("room_id",roomId);
        VideoCallAccount account = new VideoCallAccount();
        account.setStatus(-1);
        this.update(account,wrapper);
        //  呼叫组Id
        String groupId = this.callGroupPrefix + roomId;
        
        HttpHeaders headers = new HttpHeaders();
        headers.add("Accept", MediaType.APPLICATION_JSON_UTF8.toString());
        //  请求参数
        Map<String,Object> parameterMap = new HashMap<>(3);
        parameterMap.put("access_token",this.accessToken);
        parameterMap.put("operation","DELETE");
        Map<String,Object> dataMap = new HashMap<>(1);
        dataMap.put("group_ids",new String[]{ groupId });
        parameterMap.put("data",dataMap);
        String url = this.talkBackServerAddress + "/dmvphone/server/ring_group";
        Map map = this.sendRequest(url,parameterMap,headers);
        Assert.notNull(map,"删除呼叫组接口异常");
        int code = (int)map.get("ret");
        Assert.isTrue(0 == code,map.get("msg").toString());
    }

    private Map sendRequest(String url,Object parameter,HttpHeaders headers){
        HttpEntity<String> requestEntity = new HttpEntity<>(JsonUtils.objectToJson(parameter),headers);
        String result = this.restTemplate.postForObject(url, requestEntity, String.class);
        return JsonUtils.jsonToPojo(result, Map.class);
    }

}
