const redisService = require("../../../SDK/redisService").RedisService;

const BotLogic = require("./flowFsm/flow/bot/logic/index").BotLogic;
const SayLogic = require("./flowFsm/flow/say/index").SayLogic;
const EventLogic = require("./flowFsm/flow/event/logic").EventLogic;
const ResourceService =
  require("../../../service/resourceService").ResourceService;
const resourceService = new ResourceService();

const botLogic = new BotLogic();
const eventLogic = new EventLogic();
const sayLogic = new SayLogic();
const oneYearCacheTime = 365 * 24 * 60 * 60;
const oneHourCacheTime = 60 * 60;

export async function getDmOptions(resolvedEvent, oSink) {
  try {
    //获取dmInfo
    const dmId = resolvedEvent.streamId.replace("DM_", "");
    var dmInfo = JSON.parse(await redisService.get("DM_" + dmId));
    //获取上下文
    var nluInfo = dmInfo?.nluInfo;
    //eventLogic
    var event = {
      key: resolvedEvent.type,
      param: {},
    };
    var action = eventLogic.eventInputLogic(nluInfo?.botState, event).actions;
    if (action.lifecycle) {
      if (action.lifecycle.open) {
        return dialogOpen(resolvedEvent, dmInfo, oSink);
      }
      // else if (action.lifecycle.close) {
      //   return dialogClose(resolvedEvent, dmInfo, oSink);
      // }
    } else if (action.ctrl) {
      if (action.ctrl.next) {
        return getActionEvent(resolvedEvent, "next", dmInfo, oSink);
      } else if (action.ctrl.timeout) {
        return getActionEvent(resolvedEvent, "timeout", dmInfo, oSink);
      } else if (action.ctrl.utterance) {
        return getAskEvent(resolvedEvent, dmInfo, oSink);
      }
    } else if (action.log) {
      console.log("【eventInputLogic】%s ===", action.log.next, JSON.stringify(resolvedEvent.type));
    } else {
      console.log("resolvedEvent.type: ", JSON.stringify(resolvedEvent.type));
    }
  } catch (e) {
    console.error("event error", e);
    throw e;
  }
}

export async function doDmLogic(responseData, dmId) {
  if (responseData.error_code != 0) {
    return;
  }
  var dmInfo = JSON.parse(await redisService.get("DM_" + dmId));
  var nluInfo = dmInfo.nluInfo;
  var sessionId = dmInfo.dm.sessionId;
  // Nlu逻辑
  var botState = await botLogic.getBotState({}, responseData);
  // outputLogic
  var outputEventAction = eventLogic.eventOutputLogic(botState);
  // sayLogic
  var sayAction = sayLogic.getSayAction(botState);
  // 存入redis
  nluInfo["botState"] = botState;
  nluInfo["dmId"] = dmId;
  nluInfo["nluId"] = responseData.result?.session_id;;

  dmInfo.nluInfo = nluInfo;
  await redisService.set("DM_" + dmId, dmInfo, oneYearCacheTime);
  // 回调
  return toRender(sessionId, dmId, botState, sayAction, outputEventAction, nluInfo);
}

async function dialogOpen(eventData, dmInfo, oSink) {
  const streamId = eventData.streamId;
  const dmId = streamId.replace("DM_", "");
  const botKey = eventData.data.data.botKey;
  var user_intent_check = true;
  if (eventData.data.data.user_intent_check === false) {
    user_intent_check = false;
  }
  const id = eventData.data.id;
  const sessionId = dmInfo.dm.sessionId;
  const cacheBot = JSON.parse(await redisService.get(`DMToken_${sessionId}`));
  const bot = await getBotidByBotkey(botKey, dmId, cacheBot.id);
  const botId = bot.botKey;
  await redisService.set(`DMToken_${sessionId}`, { ...bot, ...cacheBot }, oneHourCacheTime);
  const partialBot = {
    botId: botId,
    botKey: botKey,
    supplierName: bot.supplierName,
  };
  dmInfo.nluInfo = {
    botInfo: partialBot,
  };
  await redisService.set("DM_" + dmId, dmInfo, oneYearCacheTime);
  if (botId) {
    const option = {
      url: oSink.config.endpoint.url,
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      data: {
        askId: id,
        sessionId: sessionId,
        botKey: botId,
        queryText: user_intent_check ? "start" : "start:user_intent_check",
        config: { premise: { supplier: bot.supplierName } },
      },
    };
    return option;
  }
}

async function getActionEvent(eventData, queryText, dmInfo, oSink) {
  var nluInfo = dmInfo.nluInfo;
  const sessionId = dmInfo.dm.sessionId;
  const nluId = nluInfo.nluId;
  const id = eventData.data.id;
  const bot = nluInfo.botInfo;
  const botId = bot.botId;
  const supplier = bot.supplierName;
  //请求nlu
  var option = {
    url: oSink.config.endpoint.url,
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    data: {
      askId: id,
      botKey: botId,
      nluId: nluId,
      sessionId: sessionId,
      queryText: queryText,
      config: { premise: { supplier: supplier } },
    },
  };
  return option;
}

async function getAskEvent(eventData, dmInfo, oSink) {
  var nluInfo = dmInfo.nluInfo;
  const sessionId = dmInfo.dm.sessionId;
  const nluId = nluInfo.nluId;
  const id = eventData.data.id;
  const bot = nluInfo.botInfo;
  const botId = bot.botId;
  const supplier = bot.supplierName;
  var option = {
    url: oSink.config.endpoint.url,
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    data: {
      askId: id,
      botKey: botId,
      nluId: nluId,
      sessionId: sessionId,
      queryText: eventData.data.data.text,
      config: { premise: { supplier: supplier } },
    },
  };
  return option;
}

async function dialogClose(eventData, dmInfo, oSink) {
  const roomId = "630322799a94c5505b9b2a16";
  const streamId = eventData.streamId;
  const dmId = streamId.replace("DM_", "");
  const sessionId = dmInfo.dm.sessionId; //关闭对话
  var message = {
    name: "message",
    action: "DIALOG_CLOSE",
    data: {},
  };
  const licodeMessage = getLicodeMessage(
    sessionId,
    roomId,
    message,
    ["default"],
    "client"
  );
  eventEmitter.emit("sendLicodeMessage", licodeMessage);
}

function toRender(sessionId, dmId, botState, sayAction, outputEventAction, nlu) {
  var data = {
    sessionId: sessionId,
    dmId: dmId,
    event: {
      type: "render",
      key: outputEventAction.eventKey,
      param: {
        seqid: "seq_" + new Date().getTime(),
        bot: {
          key: nlu?.botInfo.botKey,
          actions: sayAction,
          vars: botState.SYS_VARS
        },
      },
    },
    result:{text:sayAction[0]?.say||"你好呀"}
  };
  return data;
}

async function getBotidByBotkey(botKey, dmId, resourceId) {
  const result = await resourceService.getBotByBotKey(botKey, dmId, resourceId);

  return { botKey: result.botId, supplierName: result.supplierName };
}
