package com.xueyi.message.transfer.controller;


import com.alibaba.fastjson2.JSONObject;
import com.xueyi.common.cache.utils.SourceUtil;
import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.constant.digitalman.InitConstants;
import com.xueyi.common.core.constant.digitalman.MessageConstants;
import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.common.core.web.result.R;
import com.xueyi.message.api.transfer.domain.vo.DmActiveVo;
import com.xueyi.message.api.transfer.domain.vo.DmDeviceVo;
import com.xueyi.message.transfer.service.impl.MessageQueueServiceImpl;
import com.xueyi.system.api.authority.feign.RemoteLoginService;
import com.xueyi.system.api.device.domain.vo.DeviceTenantSourceMergeVo;
import com.xueyi.system.api.device.feign.RemoteDeviceTenantMergeService;
import com.xueyi.system.api.digitalmans.domain.dto.DmManDeviceDto;
import com.xueyi.system.api.digitalmans.domain.dto.DmSkillDto;
import com.xueyi.system.api.digitalmans.domain.dto.DmSyncDigitalmanDto;
import com.xueyi.system.api.digitalmans.domain.vo.DmBroadcastVo;
import com.xueyi.system.api.digitalmans.domain.vo.DmReceptionVo;
import com.xueyi.system.api.digitalmans.feign.RemoteBroadcastService;
import com.xueyi.system.api.digitalmans.feign.RemoteDigitalmanService;
import com.xueyi.system.api.digitalmans.feign.RemoteManDeviceService;
import com.xueyi.system.api.digitalmans.feign.RemoteReceptionService;
import com.xueyi.system.api.digitalmans.feign.RemoteSkillService;
import com.xueyi.system.api.model.Source;
import com.xueyi.system.api.organize.domain.dto.SysEnterpriseDto;
import com.xueyi.system.api.resource.feign.RemoteH5ConfigService;
import com.xueyi.system.api.staff.domain.vo.DmStaffFeature;
import com.xueyi.system.api.staff.feign.RemoteStaffService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("api")
public class ApiController {

    private static final Logger log = LoggerFactory.getLogger(ApiController.class);

    @Autowired
    RemoteStaffService remoteStaffService;

    @Autowired
    RemoteSkillService remoteSkillService;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    RemoteLoginService remoteLoginService;

    @Autowired
    RemoteDigitalmanService remoteDigitalmanService;

    @Autowired
    RemoteReceptionService remoteReceptionService;

    @Autowired
    RemoteDeviceTenantMergeService deviceTenantMergeServicel;

    @Autowired
    RemoteManDeviceService manDeviceService;

    @Autowired
    RemoteBroadcastService remoteBroadcastService;

    @Autowired
    MessageQueueServiceImpl messageQueueService;

    @Autowired
    RemoteH5ConfigService remoteH5ConfigService;


    @RequestMapping(value = "/heartbeat", method = {RequestMethod.POST})
    @ResponseBody
    public AjaxResult heartbeat(@RequestBody DmDeviceVo vo, HttpServletResponse response) {
        Long sysTime = System.currentTimeMillis();
        log.info("heartbeat: device: {} timestamp: {} ",vo.getDevId(), sysTime);
        Integer dex_res = 0;
        // 根据设备id获取租户信息
        R<DmManDeviceDto> manDeviceDtoR = manDeviceService.manDeviceInfoInner(vo.getDevId());
        if (manDeviceDtoR.isFail()) {
            return AjaxResult.warn("设备号获取失败，请检查");
        }
        // 根据设备id获取租户信息
        R<SysEnterpriseDto> enterpriseDto = remoteStaffService.tenantIdInner(vo.getEnterpriseName());
        if (enterpriseDto.isFail()) {
            return AjaxResult.warn("企业号获取失败，请检查");
        }

        // 更新心跳
        redisTemplate.opsForValue().set("group:dgman:" + vo.getDevId() + ":" + MessageConstants.HEART_BEAT_SYNC, String.valueOf(sysTime));

        String timestamp = redisTemplate.opsForValue().get("group:dgman:" + manDeviceDtoR.getData().getTId() + ":" + MessageConstants.STAFF_SYNC);


        if (timestamp != null && !timestamp.equalsIgnoreCase(vo.getTimestamp()) && Long.parseLong(timestamp) > Long.parseLong(vo.getTimestamp())) {
            dex_res += 0x01;
        }
        timestamp = redisTemplate.opsForValue().get("group:dgman:" + enterpriseDto.getData().getId() + ":" + MessageConstants.SKILL_SYNC);
        if (timestamp != null && !timestamp.equalsIgnoreCase(vo.getTimestamp()) && Long.parseLong(timestamp) > Long.parseLong(vo.getTimestamp())) {
            dex_res += 0x10;
        }
        timestamp = redisTemplate.opsForValue().get("group:dgman:" + enterpriseDto.getData().getId() + ":" + MessageConstants.MODEL_SYNC);
        if (timestamp != null && !timestamp.equalsIgnoreCase(vo.getTimestamp()) && Long.parseLong(timestamp) > Long.parseLong(vo.getTimestamp())) {
            dex_res += 0x100;
        }
        timestamp = redisTemplate.opsForValue().get("group:dgman:" + enterpriseDto.getData().getId() + ":" + MessageConstants.H5_CONFIG_SYNC);
        if (timestamp != null && !timestamp.equalsIgnoreCase(vo.getTimestamp()) && Long.parseLong(timestamp) > Long.parseLong(vo.getTimestamp())) {
            dex_res += 0x10000;
        }
//        if (!timestamp.equalsIgnoreCase(vo.getTimestamp()) && Long.parseLong(timestamp) > Long.parseLong(vo.getTimestamp())) {
//            dex_res += 0x10;
//        }
//        timestamp = redisTemplate.opsForValue().get("group:dgman:" + enterpriseDto.getData().getId() + ":" + MessageConstants.MODEL_SYNC);
//        if (!timestamp.equalsIgnoreCase(vo.getTimestamp()) && Long.parseLong(timestamp) > Long.parseLong(vo.getTimestamp())) {
//            dex_res += 0x100;
//        }
//        Source source = SourceUtil.getSourceCache(enterpriseDto.getData().getStrategyId());
//        // 获取人员及访客更新内容
//        R<List<DmStaffFeature>> staffFeatureList = remoteStaffService.listInner(vo.getDevId(), vo.getTimestamp(), enterpriseDto.getData().getId(),source.getMaster(), SecurityConstants.INNER);
//        if (staffFeatureList.isFail())
//            return AjaxResult.warn("新增失败，请检查！");
//        if (staffFeatureList.getData() != null && staffFeatureList.getData().size() > 0) {
//            //判断有更新，返回提醒
//            dex_res += 0x1;
//        }

        // 获取问题更新内容

        return AjaxResult.success(dex_res);
    }

    @RequestMapping(value = "/update", method = {RequestMethod.POST})
    @ResponseBody
    public AjaxResult update(@RequestBody DmDeviceVo vo, HttpServletResponse response) {
        String timestamp = vo.getTimestamp();
        // 根据设备id获取租户信息
        R<DmManDeviceDto> manDeviceDtoR = manDeviceService.manDeviceInfoInner(vo.getDevId());
        if (manDeviceDtoR.isFail() || manDeviceDtoR.getData() == null) {
            return AjaxResult.warn("设备号获取失败，请检查");
        }
        Source source = SourceUtil.getSourceCache(manDeviceDtoR.getData().getStrategyId());
        if (vo.getType() != null) {
            switch (vo.getType()) {
                // 人员信息
                case 0:
                    timestamp = redisTemplate.opsForValue().get("group:dgman:" + manDeviceDtoR.getData().getTId() + ":" + MessageConstants.STAFF_SYNC);
                    if (timestamp == null) {
                        AjaxResult.warn("当前时间戳获取失败");
                    }
                    R<List<DmStaffFeature>> staffFeatureList = remoteStaffService.listInner(vo.getDevId(), vo.getTimestamp(), manDeviceDtoR.getData().getTId(), source.getMaster(), SecurityConstants.INNER);
                    if (staffFeatureList.isFail())
                        return AjaxResult.warn("新增失败，请检查！");
                    staffFeatureList.getData().forEach(item ->
                    {
                        if (item.getFeature() != "") {
                            String ops_str = item.getFeature().substring(1, item.getFeature().indexOf("]"));
                            item.setDFeatures(Arrays.stream(ops_str.split(",")).map(Double::valueOf).collect(Collectors.toList()));
                        }
                        item.setFeature("");
                    });
                    return AjaxResult.success(staffFeatureList.getData()).put("timestamp", timestamp);
                case 1:
                    log.info("=========租户号：{}，数据源：{}, 设备号：{}",manDeviceDtoR.getData().getTId(), source.getMaster(), vo.getDevId());
                    R<List<DmSkillDto>> skillList = remoteSkillService.skilllistInner(vo.getDevId(), vo.getTimestamp(), manDeviceDtoR.getData().getTId(), source.getMaster(), SecurityConstants.INNER);
                    if (skillList.isFail())
                        return AjaxResult.warn("新增失败，请检查");
                    return AjaxResult.success(skillList.getData()).put("timestamp", timestamp);
                case 2:
                    R<DmSyncDigitalmanDto> syncDmDto = remoteDigitalmanService.listInner(manDeviceDtoR.getData().getManCode(), vo.getTimestamp(), manDeviceDtoR.getData().getTId(), source.getMaster(), SecurityConstants.INNER);
                    if (syncDmDto.isFail())
                        return AjaxResult.warn("新增失败，请检查");
                    // 添加播报信息
                    R<List<DmBroadcastVo>> broadcastVoR = remoteBroadcastService.innerlist(manDeviceDtoR.getData().getManCode(), manDeviceDtoR.getData().getTId(), source.getMaster(), SecurityConstants.INNER);
                    if (!broadcastVoR.isFail()) {
                        syncDmDto.getData().setBroadcast(broadcastVoR.getData());
                    }

                    return AjaxResult.success(syncDmDto.getData()).put("timestamp", timestamp);
                case 3:
                    R<DmReceptionVo> receptionVo = remoteReceptionService.getReceptionTaskInner(manDeviceDtoR.getData().getManCode(), manDeviceDtoR.getData().getTId(), source.getMaster(), SecurityConstants.INNER);
                    if (receptionVo.isFail()) {
                        return AjaxResult.warn("接待模式任务获取失败，请检查");
                    }


//                    JSONObject jsObject = new JSONObject();
//                    jsObject.put("code",200);
//                    JSONObject data = new JSONObject();
//                    data.put("name", "A市长考察");
//                    data.put("date", "07-23");
//                    JSONArray gArray = new JSONArray();
//                    gArray.add(1676570397299970049L);
//                    data.put("guide", gArray);
//                    JSONArray fArray = new JSONArray();
//                    fArray.add(1682948239952818177L);
//                    fArray.add(1683035071285399554L);
//                    data.put("first", fArray);
//                    JSONArray sArray = new JSONArray();
//                    sArray.add(1682328924238446593L);
//                    data.put("second", sArray);
//
//                    jsObject.put("data",data);
//                    jsObject.put("msg","success");
                    return AjaxResult.success(receptionVo.getData());
                case 4:
                    R<String> propertyR = remoteH5ConfigService.syncH5Config(manDeviceDtoR.getData().getTId().toString());
                    if (propertyR.isFail()) {
                        return AjaxResult.warn("配置同步失败，请检查");
                    }
                    return AjaxResult.success(propertyR.getData());
            }
        }
        return AjaxResult.success();
    }

    @RequestMapping(value = "/activate", method = {RequestMethod.POST})
    @ResponseBody
    public AjaxResult activate(@RequestBody DmActiveVo vo, HttpServletResponse response) {
        // 判断参数完整性
        if (vo.getSecret() == null || vo.getSecret().equalsIgnoreCase("")) {
            return AjaxResult.warn("激活码不能为空");
        }

        // 根据密钥获取账户信息
        R<DeviceTenantSourceMergeVo> deviceTenantSourceMergeVoR = deviceTenantMergeServicel.selectDeviceSNTenantSourceMerge(vo.getSncode(), vo.getSecret());
        if (deviceTenantSourceMergeVoR.isFail()) {
            return AjaxResult.warn(deviceTenantSourceMergeVoR.getMsg());
        }
        vo.setActivateTime(new Date());
        // 设备是否已绑定其他账号
        R<DmManDeviceDto> manDeviceDtoR = manDeviceService.manDeviceInfoInner(vo.getSncode());
//        if (manDeviceDtoR.getData() != null) {
//            return AjaxResult.warn("设备号已绑定其他账号");
//        }
        R<Integer> regR = manDeviceService.manDeviceInfoInnerUpdate(vo);
        if (regR.getData() == 0) {
            return AjaxResult.warn("更新设备信息失败，请查询log");
        }
        // 调用初始化处理（数字人，数字人设备，形象，技能）
        R<Integer> initResult = remoteDigitalmanService.initInner(vo.getSecret(), deviceTenantSourceMergeVoR.getData().getTenantId(), deviceTenantSourceMergeVoR.getData().getSourceSlave(), SecurityConstants.INNER);
        // 根据状态返回结果
        if (initResult.isFail()) {
            return AjaxResult.warn("绑定数字人失败，请联系后台人员");
        }
        // 更新心跳状态
        redisTemplate.opsForValue().set("group:dgman:" + vo.getSncode() + ":" + MessageConstants.HEART_BEAT_SYNC, String.valueOf(System.currentTimeMillis()));
        //redisTemplate.opsForHash().(MessageConstants.REDIS_GROUP_DEVICE_HEADER,devId,dto);
        //redisTemplate.
        return AjaxResult.success();
    }

    /**
     * 获取设备在线状态
     */
    @RequestMapping(value = "/device_online_status/{devId}", method = {RequestMethod.GET})
    @ResponseBody
    public AjaxResult getDeviceOnlineStatus(@RequestParam(value = "devId") String devId, HttpServletResponse response) {
        // 获取设备心跳状态
        String timestamp = redisTemplate.opsForValue().get("group:dgman:" + devId + ":" + MessageConstants.HEART_BEAT_SYNC);

        if (timestamp == null || timestamp == "") {
            // 如果设备缓存获取不到，查询数据库是否存在该设备
            R<DmManDeviceDto> manDeviceDtR = manDeviceService.manDeviceInfoInner(devId);
            if (manDeviceDtR.isFail() || manDeviceDtR.getData() == null) {
                // 如果设备查询不到，返回未激活
                return AjaxResult.success(InitConstants.DEVICE_ACTIVATE_STATUS_NOT_ACTIVATE);
            }
            return AjaxResult.success(InitConstants.DEVICE_ACTIVATE_STATUS_OFFLINE);
        }
        // 设备存在缓存时判断是否超过10min
        return AjaxResult.success(System.currentTimeMillis() - Long.parseLong(timestamp) > 10 * 60 * 1000 ? InitConstants.DEVICE_ACTIVATE_STATUS_OFFLINE : InitConstants.DEVICE_ACTIVATE_STATUS_ONLINE);
    }

    /**
     * @return manCount
     * serviceTimeCount
     * chatTimes
     * chatDurationCount
     * skillExecuteTimes
     * <p>
     * recognizedPersonCount
     * servicePerCount
     * <p>
     * receptionServiceCount
     * meetingServiceCount
     * visitServiceCount
     * largeModelKnowledgeBaseGroupChangeNum
     * largeModelKnowledgeBaseChangeNum
     * @Author yangkai
     * @Description //TODO
     * @Date 2023/8/11
     * @Param
     **/
    @RequestMapping(value = "/broadcast", method = {RequestMethod.GET})
    @ResponseBody
    public R broadcast(@RequestParam(value = "channel") String channel) {
        try {
            log.info("broadcast----exec");
            JSONObject json = new JSONObject();
            R<JSONObject> objectR = remoteDigitalmanService.mansInfo();
            log.info("mansInfo:{}", objectR.getData());
            JSONObject jsonObj = objectR.getData();
            jsonObj.keySet().forEach(key -> json.put(key, jsonObj.get(key)));
            String str = json.toJSONString();
            log.info("broadcast:{}", str);
            messageQueueService.broadcast(channel, str);
            return R.ok(str);
        } catch (Exception e) {
            e.printStackTrace();
            return R.fail(e.getMessage());
        }
    }

    @RequestMapping(value = "/get_activate/{snCode}", method = {RequestMethod.GET})
    @ResponseBody
    public AjaxResult activate(@PathVariable(value = "snCode") String snCode, HttpServletResponse response) {
        R<DmManDeviceDto> manDeviceDtR = manDeviceService.manDeviceInfoInner(snCode);
        if (manDeviceDtR.getData() == null) {

            return AjaxResult.success("false");
        }
        log.info(manDeviceDtR.getData().toString());
        return AjaxResult.success("true");
    }

    @RequestMapping(value = "/get_config_info/{deviceId}", method = {RequestMethod.GET})
    @ResponseBody
    public AjaxResult getConfigInfo(@PathVariable(value = "deviceId") String deviceId, HttpServletResponse response) {
        // 根据设备id获取租户信息
        R<DmManDeviceDto> manDeviceDtoR = manDeviceService.manDeviceInfoInner(deviceId);
        String tenantId = null;
        if (manDeviceDtoR.isOk() && manDeviceDtoR.getData() != null) {
            tenantId = manDeviceDtoR.getData().getTId().toString();
        }
        R<String> propertyR = remoteH5ConfigService.syncH5Config(tenantId);
        if (propertyR.isFail()) {
            return AjaxResult.warn("配置同步失败，请检查");
        }
        return AjaxResult.success(propertyR.getData());
    }
}
