package com.qiuguo.iot.box.websocket.api.handler;

import com.alibaba.fastjson.JSONObject;
import com.qiuguo.iot.base.enums.AskTypeEnum;
import com.qiuguo.iot.base.enums.PlayEnum;
import com.qiuguo.iot.base.enums.RespCodeEnum;
import com.qiuguo.iot.base.utils.StringUtils;
import com.qiuguo.iot.box.websocket.api.domain.BaseSession;
import com.qiuguo.iot.box.websocket.api.domain.box.BoxSession;
import com.qiuguo.iot.box.websocket.api.domain.box.resp.BoxMessageResp;
import com.qiuguo.iot.box.websocket.api.domain.user.UserTalkMessage;
import com.qiuguo.iot.box.websocket.api.filter.LogMdcConfiguration;
import com.qiuguo.iot.data.entity.device.DeviceUserBindEntity;
import com.qiuguo.iot.data.entity.device.DeviceUserTalkRecordEntity;
import com.qiuguo.iot.data.entity.system.SystemTalkBindDeviceEntity;
import com.qiuguo.iot.data.request.device.DeviceUserBindRequest;
import com.qiuguo.iot.data.request.qwen.TongYiCommunicationRest;
import com.qiuguo.iot.data.request.system.SystemTalkBindDeviceRequest;
import com.qiuguo.iot.data.request.third.ThirdWeatherInfoRequest;
import com.qiuguo.iot.data.resp.third.MusicResp;
import com.qiuguo.iot.data.resp.third.weather.TianqiapiItemResp;
import com.qiuguo.iot.data.service.device.DeviceUserBindService;
import com.qiuguo.iot.data.service.device.DeviceUserTalkRecordService;
import com.qiuguo.iot.data.service.system.SystemAddressService;
import com.qiuguo.iot.data.service.system.SystemTalkBindDeviceService;
import com.qiuguo.iot.third.nlp.action.Action;
import com.qiuguo.iot.third.nlp.action.ActionTime;
import com.qiuguo.iot.third.nlp.action.Actions;
import com.qiuguo.iot.third.query.TuyaQuery;
import com.qiuguo.iot.third.resp.SongInfoResponse;
import com.qiuguo.iot.third.service.*;
import lombok.extern.slf4j.Slf4j;
import org.hswebframework.web.api.crud.entity.PagerResult;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.reactive.socket.WebSocketSession;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import javax.annotation.Resource;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class BaseWebSocketProcess {


    @Resource
    protected DeviceUserBindService deviceUserBindService;


    @Autowired
    protected TuyaDeviceService tuyaDeviceService;

    @Resource
    protected SystemTalkBindDeviceService systemTalkBindDeviceService;

    @Autowired
    protected WeatherService weatherService;

    @Autowired
    protected SystemAddressService systemAddressService;

    @Autowired
    protected DeviceUserTalkRecordService deviceUserTalkRecordService;

    @Autowired
    protected MusicService musicService;

    @Autowired
    protected QWenService qwenService;


    protected static ConcurrentHashMap<Long, BaseSession> userGroup = new ConcurrentHashMap<>();

    protected static ConcurrentHashMap<String, BoxSession> boxGroup = new ConcurrentHashMap<>();

    protected static String apiType = "api-type";
    protected static String apiToken = "api-token";

    private void toQianWen(Action action, BaseSession baseSession){
        TongYiCommunicationRest tongYiCommunicationRest = new TongYiCommunicationRest();
        tongYiCommunicationRest.setText(action.getAsk());
        tongYiCommunicationRest.setStatus("2");
        if(this instanceof BoxWebSocketHandler){
            tongYiCommunicationRest.setOnlyId(baseSession.getSn());
        }else{
            tongYiCommunicationRest.setOnlyId(baseSession.getUserId().toString());
        }
        qwenService.communication(tongYiCommunicationRest).map(data ->{
            BoxMessageResp resp = new BoxMessageResp();
            resp.setType(0);
            if(data.getCode() == 200){
                resp.setText(data.getResut());
            }else{
                resp.setText("我还在努力学习中，暂时无法理解");
            }

            sendMessage(action, baseSession, resp);
            return data;
        }).subscribeOn(Schedulers.boundedElastic()).subscribe();
    }

    protected void processAction(Actions actions, Long userId, BaseSession baseSession) {
        if(actions.getActions() == null || actions.getActions().size() == 0){
            //调用千问回答\
            log.info("调用千问");
            Action action = new Action();
            action.setAsk(actions.getRecordText());
            action.setAction(actions.getRecordText());
            toQianWen(action, baseSession);
        }
        for (Action action : actions.getActions()
        ) {
            log.info("匹配到自定义指令{}", action.getSystemTalkAnswerConfigEntity());
            if(action.getSystemTalkAnswerConfigEntity() == null){
                log.info("调用千问");
                toQianWen(action, baseSession);

                //
            }else if(action.getSystemTalkAnswerConfigEntity().getAnswerType().equals(AskTypeEnum.IOT.getCode())){

                if(StringUtils.isNotEmpty(action.getName())){

                    if(action.getDeviceUserBindEntity() == null){
                        log.info("匹配时未找到对应的设备，模糊匹配{}", action.getName());
                        DeviceUserBindRequest deviceUserBindRequest = new DeviceUserBindRequest();
                        deviceUserBindRequest.setUserId(userId);
                        deviceUserBindRequest.setPageSize(2);
                        deviceUserBindRequest.setBindName(action.getName());

                        //查询是否有相关设备
                        deviceUserBindService.selectDeviceUserBindsByRequest(deviceUserBindRequest)
                                .defaultIfEmpty(new PagerResult<>(0, null))
                                .map(binds ->{
                                    if(binds.getTotal() == 0){
                                        //返回告诉没有备
                                        BoxMessageResp resp = new BoxMessageResp();
                                        resp.setType(action.getSystemTalkAnswerConfigEntity().getAnswerType());
                                        resp.setText("未找到" + action.getName() + "设备，无法操做！");
                                        sendMessage(action, baseSession, resp);
                                    }else if(binds.getTotal() > 1){
                                        //返回告诉有多个设备，请详细说明具体说明设备
                                        BoxMessageResp resp = new BoxMessageResp();
                                        resp.setType(action.getSystemTalkAnswerConfigEntity().getAnswerType());
                                        resp.setText("您有多个" + action.getName() + "相同设备，请明确说明");
                                        sendMessage(action, baseSession, resp);
                                    }else{
                                        //查询是否有相关指令绑定
                                        action.setDeviceUserBindEntity(binds.getData().get(0));
                                        controllerDevice(action, action.getDeviceUserBindEntity(), baseSession, action.getName());

                                    }
                                    return Mono.empty();
                                }).subscribe();
                    }else{
                        log.info("匹配时已找到对应的设备{}", action.getName());
                        controllerDevice(action, action.getDeviceUserBindEntity(), baseSession, action.getName());
                    }

                }else{
                    BoxMessageResp resp = new BoxMessageResp();
                    resp.setType(action.getSystemTalkAnswerConfigEntity().getAnswerType());
                    resp.setText("未找到对应的设备");
                    sendMessage(action, baseSession, resp);
                }

            }else if(action.getSystemTalkAnswerConfigEntity().getAnswerType().equals(AskTypeEnum.WEATHER.getCode())){
                ThirdWeatherInfoRequest req = new ThirdWeatherInfoRequest();
                //String city = "";
                if(action.getLbs() != null && action.getLbs().size() > 0){
                    //根据地址查询天气
                    // city = ;
                    req.setCity(action.getLbs().get(action.getLbs().size() - 1));
                }else{
                    //使用IP查询天气
                    req.setIp("115.205.2.137");
                }
                if(action.getTime() == null){
                    action.setTime(new ActionTime());
                    action.getTime().setTime("今天");
                }
                weatherService.tianqiApi(req).map(t ->{
                    log.info("查询的天气{}", JSONObject.toJSONString(t));
                    TianqiapiItemResp item = null;

                    if(StringUtils.isNotEmpty(action.getTime().getDateTime())){
                        //匹配对应的日期
                        for (TianqiapiItemResp itemResp : t.getData())
                        {
                            if(action.getTime().getDateTime().equals(itemResp.getDate())){
                                item = itemResp;
                                break;
                            }
                        }

                    }else{
                        item = t.getData().get(0);
                    }
                    String msg = "";
                    if(item != null){
                        //返回给客户端播报内容
                        msg = t.getCity() + action.getTime().getTime() + "天气"
                                + item.getNarrative().replace("每 km / h", "千米每小时")
                                + "，空气质量" + item.getAir_level()
                                + "，湿度" + item.getHumidity() + "，最低气温" + item.getTem2() + "°C";

                    }else{
                        msg = action.getSystemTalkAnswerConfigEntity().getAnswerValueFaild();

                        log.info("执行指令失败");
                    }
                    BoxMessageResp resp = new BoxMessageResp();
                    resp.setType(action.getSystemTalkAnswerConfigEntity().getAnswerType());
                    resp.setText(msg);
                    sendMessage(action, baseSession, resp);
                    return t;
                }).subscribe();
            }else if(action.getSystemTalkAnswerConfigEntity().getAnswerType().equals(AskTypeEnum.MUSIC.getCode())){

                String search = action.getAsk().replaceAll(action.getAction(), "").replaceAll("的", "");
                if(StringUtils.isNotEmpty(action.getPName())){
                    search = search.replaceAll(action.getPName(), "");
                }
                BoxMessageResp resp = new BoxMessageResp();
                if(action.getSystemTalkAnswerConfigEntity().getPlayType().equals(PlayEnum.START.getCode())){
                    musicService.searchMusic(search, 1).defaultIfEmpty(new ArrayList<>()).map(resultSongs -> {
                        //BoxMessageResp resp = new BoxMessageResp();
                        MusicResp musicResp = new MusicResp();
                        if(resultSongs.size() > 0){
                            //
                            SongInfoResponse.ResultSong song = resultSongs.get(0);
                            musicResp.setPlay(PlayEnum.START.getCode());
                            musicResp.setName(song.getName());
                            musicResp.setUrl(song.getUrl());
                            musicResp.setSinger(song.getArtistName());
                            resp.setText("现在为您播放" + song.getName() +
                                    (StringUtils.isNotEmpty(song.getArtistName()) ? ("来自" + song.getArtistName()) : ""));
                        }else{
                            musicResp.setPlay(PlayEnum.NONE.getCode());
                            resp.setText("未找到相关资源");
                        }
                        resp.setMusic(musicResp);
                        resp.setType(action.getSystemTalkAnswerConfigEntity().getAnswerType());

                        sendMessage(action, baseSession, resp);
                        return resultSongs;
                    }).subscribe();
                }else if(baseSession.getMusic() != null){
                    //做相应的动作
                    baseSession.getMusic().setPlay(action.getSystemTalkAnswerConfigEntity().getPlayType());
                    resp.setMusic(baseSession.getMusic());
                    resp.setText(action.getSystemTalkAnswerConfigEntity().getAnswerValue().replace("#name#", baseSession.getMusic().getName()));
                    resp.setType(action.getSystemTalkAnswerConfigEntity().getAnswerType());
                    sendMessage(action, baseSession, resp);
                }else{
                    resp.setType(AskTypeEnum.TTS.getCode());
                    resp.setText("目前无播放资源，无法操作");
                    sendMessage(action, baseSession, resp);
                }

            }
        }
    }

    private void controllerDevice(Action action, DeviceUserBindEntity deviceUserBindEntity, BaseSession baseSession, String deviceName) {

        SystemTalkBindDeviceRequest systemTalkBindDeviceRequest = new SystemTalkBindDeviceRequest();
        systemTalkBindDeviceRequest.setCategoryCode(deviceUserBindEntity.getCategoryCode());
        systemTalkBindDeviceRequest.setSystemTalkId(action.getSystemTalkAnswerConfigEntity().getId());
        if(StringUtils.isNotEmpty(action.getActionCommand())){
            systemTalkBindDeviceRequest.setAskCommon(action.getActionCommand());
        }
        systemTalkBindDeviceService.selectSystemTalkBindDeviceByRequest(systemTalkBindDeviceRequest)
                .defaultIfEmpty(new SystemTalkBindDeviceEntity())
                .map(systemTalkBindDeviceEntity -> {
                    if(systemTalkBindDeviceEntity.getId() == null){
                        //通知不支持的指令
                        BoxMessageResp resp = new BoxMessageResp();
                        resp.setType(action.getSystemTalkAnswerConfigEntity().getAnswerType());
                        resp.setText(deviceName + "不支持" + action.getAction() + "指令！");
                        sendMessage(action, baseSession, resp);

                    }else{
                        //调用涂鸦
                        TuyaQuery query = new TuyaQuery();
                        query.setDeviceId(deviceUserBindEntity.getOtherDeviceId());
                        query.setValue(action.getStatus());
                        query.setUserHandlingDeviceId(systemTalkBindDeviceEntity.getUserHandlingId());
                        tuyaDeviceService.controlDevice(query).map(isOk ->{
                            String msg = "";
                            if(isOk.getCode().equals(RespCodeEnum.SUCESS.getCode())){
                                //通知打开灯成功
                                msg = systemTalkBindDeviceEntity.getAnswerValue().replaceAll("#name#", deviceName);
                                if(StringUtils.isNotEmpty(action.getStatus())){
                                    msg = msg.replace("#value#", action.getStatus());
                                }

                                log.info("执行指令");
                            }else{
                                //通知开灯失败;
                                msg = systemTalkBindDeviceEntity.getAnswerValueFaild().replaceAll("#name#", deviceName);
                                log.info("执行指令失败");
                            }
                            BoxMessageResp resp = new BoxMessageResp();
                            resp.setType(action.getSystemTalkAnswerConfigEntity().getAnswerType());
                            resp.setText(msg);
                            sendMessage(action, baseSession, resp);

                            return isOk;
                        }).subscribe();
                    }
                    return systemTalkBindDeviceEntity;
                }).subscribe();
    }

    private void sendMessage(Action action, BaseSession baseSession, BoxMessageResp resp){

        DeviceUserTalkRecordEntity talkRecord = new DeviceUserTalkRecordEntity();
        talkRecord.setAskType(resp.getType());
        talkRecord.setAskValue(action.getAsk());
        talkRecord.setAskKey(action.getAction());
        talkRecord.setAnswerValue(resp.getText());
        talkRecord.setUserId(baseSession.getUserId());
        talkRecord.setDeviceId(baseSession.getDeviceId());
        if(resp.getType().equals(AskTypeEnum.MUSIC.getCode())) {
            //客户端推送的
            if(this instanceof CustomerWebSocketHandler) {
                log.info("推送Box播放音乐");
                BoxSession boxSession = getBoxSessionWithSn(baseSession.getSn());
                if(boxSession != null){
                    boxSession.getSink().next(baseSession.getSession().textMessage(JSONObject.toJSONString(resp)));
                    //记录音乐状态
                    if(resp.getMusic().getPlay().equals(PlayEnum.STOP.getCode())){
                        //去掉内存中音乐同步对象
                        boxSession.setMusic(null);
                        baseSession.setMusic(null);
                    }else{
                        boxSession.setMusic(resp.getMusic());
                        baseSession.setMusic(resp.getMusic());
                    }
                }else{
                    log.info("设备sn：{}不在线，无法播放", baseSession.getSn());
                    resp.setText("设备不在线，无法播放");
                    if(resp.getMusic().getPlay().equals(PlayEnum.STOP.getCode())){
                        //去掉内存中音乐同步对象
                        baseSession.setMusic(null);
                    }else{
                        baseSession.setMusic(resp.getMusic());
                    }
                }
            }else{//果box的
                //记录音乐状态
                BaseSession userSession = getUserSessionWithUserId(baseSession.getUserId());
                //记录音乐状态
                //去掉内存中音乐同步对象
                if(userSession != null){
                    if(resp.getMusic().getPlay().equals(PlayEnum.STOP.getCode())){
                        baseSession.setMusic(null);
                        userSession.setMusic(null);
                    }else{
                        baseSession.setMusic(resp.getMusic());
                    }
                    //如果在线推送用户端
                }else{
                    if(resp.getMusic().getPlay().equals(PlayEnum.STOP.getCode())){
                        baseSession.setMusic(null);
                    }else{
                        baseSession.setMusic(resp.getMusic());
                    }
                }

            }
        }
        deviceUserTalkRecordService.insertDeviceUserTalkRecord(talkRecord).map(i ->{
            String msg = JSONObject.toJSONString(resp);
            log.info("推送通知到端msg:{}", msg);
            if(this instanceof BoxWebSocketHandler){
               log.info("果box聊天记录，同步到客户端");
                BaseSession userSession = getUserSessionWithUserId(baseSession.getUserId());
                if(userSession != null){
                    userSession.getSink().next(baseSession.getSession().textMessage(msg));
                }
            }
            baseSession.getSink().next(baseSession.getSession().textMessage(msg));

            return Mono.empty();
        }).subscribe();//保存聊天记录

    }

    public BoxSession getBoxSessionWithSn(String sn) {
        if(boxGroup.containsKey(sn)){
            return boxGroup.get(sn);
        }
        return null;
    }

    public BaseSession getUserSessionWithUserId(Long userId) {
        if(userGroup.containsKey(userId)){
            return userGroup.get(userId);
        }
        return null;
    }
}
