package com.tuoheng.admin.service.third.dsp;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tuoheng.admin.entity.Business;
import com.tuoheng.admin.entity.Inspection;
import com.tuoheng.admin.entity.LiveChannel;
import com.tuoheng.admin.enums.AiAnalyseStatusEnum;
import com.tuoheng.admin.enums.InspectionStatusEnum;
import com.tuoheng.admin.enums.MarkEnum;
import com.tuoheng.admin.enums.code.inspection.EditInspectionStatusCodeEnum;
import com.tuoheng.admin.mapper.BusinessMapper;
import com.tuoheng.admin.mapper.LiveChannelMapper;
import com.tuoheng.admin.request.inspection.MissionStatusRequest;
import com.tuoheng.admin.vo.DspCallbackVo;
import com.tuoheng.admin.websocket.WebSocketService;
import com.tuoheng.common.core.utils.DateUtils;
import com.tuoheng.common.core.utils.JacksonUtil;
import com.tuoheng.common.core.utils.JsonResult;
import com.tuoheng.common.core.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Locale;
@Slf4j
@Service
public class StartAIService {

    /**
     * DSP服务API接口域名
     */
    @Value("${tuoheng.dsp-domain-url:}")
    private String dspDomainUrl;

    @Value("${tuoheng.dsp-callback-url:}")
    private String dspCallbackUrl;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private LiveChannelMapper liveChannelMapper;

    @Autowired
    private BusinessMapper businessMapper;

    @Autowired
    private WebSocketService webSocketService;

    /**
     * 调用DSP接口
     *
     * @param inspection
     * @param pushUrl
     * @param pullUrl
     *
     * @return
     */
    public JsonResult startAI(Inspection inspection, String pushUrl, String pullUrl) {
        log.info("调用DSP进行分析, inspectionId={}, pushUrl:{}, pullUrl:{}", inspection.getId(), pushUrl, pullUrl);

        String dspServiceInstId = inspection.getDspServiceInstId();
        JsonResult result = this.callDsp(dspServiceInstId, pushUrl, pullUrl);

        if (0 != result.getCode()) {
            // 如果调用DSP失败就直接失败！
            log.info("调用DSP数据失败：{}", result.getMsg());
            return result;
        }

        JSONObject jsonObject = (JSONObject) result.getData();
        DspCallbackVo dspCallbackVo = JSON.toJavaObject(jsonObject.getJSONObject("data"), DspCallbackVo.class);
        log.info("dsp响应体：{}", JacksonUtil.obj2StringPretty(dspCallbackVo));

        // 处理通道数据
        this.liveChannelHandle(inspection, dspCallbackVo);

        // 将请求id和业务id消息存入数据库，用于监听获取任务信息
        this.businessHandle(inspection, dspCallbackVo);

        return JsonResult.success();
    }

    /**
     * 调用DSP接口
     *
     * @param dspServiceInstId
     * @param pushUrl
     * @param pullUrl
     *
     * @return
     */
    public JsonResult callDsp(String dspServiceInstId, String pushUrl, String pullUrl) {
        String url = String.format(Locale.ENGLISH, "%s/api/web/serviceInst/%s/application", dspDomainUrl, dspServiceInstId);
        JSONObject jsonObject = this.getJSONObject(pushUrl, pullUrl);
        log.info("调用DSP服务, url:{}", url);
        log.info("调用DSP服务, jsonObject:{}", jsonObject);

        String result = SendPost.doPost(url, jsonObject, null);
        log.info("调用DSP服务, result:{}", result);

        JSONObject responseJson = JSONObject.parseObject(result);
        if (responseJson.getIntValue("code") == 0) {
            String requestId = responseJson.getJSONObject("data").getString("requestId");
            log.info("调用DSP进行分析，dsp实时调用响应，requestId：{}", requestId);
        } else {
            log.error("dsp实时调用失败：{}", responseJson);
            return JsonResult.error(EditInspectionStatusCodeEnum.TASK_ANALYSIS_FAILED.getCode(), EditInspectionStatusCodeEnum.TASK_ANALYSIS_FAILED.getMsg());
        }
        return JsonResult.success(responseJson);
    }

    private JSONObject getJSONObject(String pushUrl, String pullUrl) {
        JSONObject request = new JSONObject();
        JSONArray configList = new JSONArray();
        JSONObject instConfigMode = new JSONObject();
        instConfigMode.put("ename", "service_mode");
        instConfigMode.put("evalue", "1");
        configList.add(instConfigMode);
        JSONObject instConfigUrl = new JSONObject();
        instConfigUrl.put("ename", "callback_url");
        instConfigUrl.put("evalue", dspCallbackUrl);
        configList.add(instConfigUrl);
        request.put("serviceInstConfigList", configList);

        JSONArray reqList = new JSONArray();

        JSONObject instReqUrlPush = new JSONObject();
        instReqUrlPush.put("ename", "push_url");
        instReqUrlPush.put("evalue", pushUrl);
        reqList.add(instReqUrlPush);

        JSONObject instReqUrlPull = new JSONObject();
        instReqUrlPull.put("ename", "pull_url");
        instReqUrlPull.put("evalue", pullUrl);
        reqList.add(instReqUrlPull);
        request.put("serviceInstReqList", reqList);
        return request;
    }

    /**
     * 处理通道数据
     *
     * @param inspection
     * @param dspCallbackVo
     */
    private void liveChannelHandle(Inspection inspection, DspCallbackVo dspCallbackVo) {
        log.info("进入处理通道数据方法");
        //  通道表新增
        LiveChannel liveChannel = this.buildLiveChannel(inspection, dspCallbackVo);
        // 查验是否存在
        LiveChannel liveChannelQuery = liveChannelMapper.selectOne(new LambdaQueryWrapper<LiveChannel>()
                .eq(LiveChannel::getInspectionId, inspection.getId())
                .eq(LiveChannel::getMark, MarkEnum.VALID.getCode()));
        if (liveChannelQuery == null) {
            // 添加通道使用记录
            liveChannel.setCreateTime(DateUtils.now());
            liveChannelMapper.insert(liveChannel);
        } else {
            // 更新通道使用记录
            liveChannel.setId(liveChannelQuery.getId());
            liveChannelMapper.updateById(liveChannel);
        }

        webSocketService.accidentNotice(inspection.getTenantId());
    }

    private LiveChannel buildLiveChannel(Inspection inspection, DspCallbackVo dspCallbackVo) {
        LiveChannel liveChannel = new LiveChannel();
        liveChannel.setTenantId(inspection.getTenantId());
        liveChannel.setDeptId(inspection.getDeptId());
        liveChannel.setInspectionId(inspection.getId());
        liveChannel.setChannelCode("0");
        liveChannel.setPushUrl(dspCallbackVo.getPushUrl());
        liveChannel.setPullUrl(dspCallbackVo.getPlayUrl());
        liveChannel.setAipushUrl(dspCallbackVo.getAipushUrl());
        liveChannel.setAipullUrl(dspCallbackVo.getAiplayUrl());
        return liveChannel;
    }

    private void businessHandle(Inspection inspection, DspCallbackVo dspCallbackVo) {
        // 将请求id和业务id消息存入数据库，用于监听获取任务信息
        Business business = new Business();
        business.setTenantId(inspection.getTenantId());
        business.setMsgId(dspCallbackVo.getRequestId());
        business.setType(1);
        business.setTypeId(inspection.getId());
        business.setCreateTime(DateUtils.now());
        businessMapper.insert(business);
    }
}
