import Msg from "../utils/msg"; // 确保路径是正确的
import SnsSigCheck from "../utils/snsSigCheck";
import * as os from "os"; // 导入os模块用于获取服务器IP
import {
  Account,
  QQAppId,
  QQAppKey,
  QQ_PROD_URL,
  GET_INFO_URL,
  UIC_FILTER_URL,
  DA_WAN_KA_PAY_URL,
  REPORT_KEY,
  IS_LOGIN_URL,
  DA_WAN_KA_URL,
  BLUE_VIP_INFO_URL,
  BUY_GOODS_URL,
  QQ_DEV_URL,
  PAY_DEV_APP_KEY,
  REPORT_URL,
  PAY_PROD_APP_KEY,
  PAY_PROD_APP_KEY_2,
  PAY_DEV_APP_KEY_2,
  ORDER_SIGN_KEY,
} from "../config/thirdParams";
import {
  generateOrderNumber,
  formatDate,
  getServerList,
  getClientIp,
} from "../utils/common";
import { PaymentHelper } from "../utils/PaymentHelper";
import { SignatureVerifier } from "../utils/SignatureVerifier";
const dayjs = require("dayjs");
const Server = require("../model/ServerModel");
const CryptoJS = require("crypto-js");
const Order = require("../model/OrderModel");
const logger = require("../utils/log");
const axios = require("axios");
const QQ_API_URL = QQ_PROD_URL;
const IS_DEV = false;

/**
 * QQ支付回调处理
 */
const CallPayQQ = async (ctx) => {
  let ret = {
    ret: 1,
    msg: "发货失败",
  };

  let data = ctx.request.query;
  logger.info("QQ支付回调参数:", { url: ctx.href, params: data });

  let Key = IS_DEV ? PAY_DEV_APP_KEY_2 : PAY_PROD_APP_KEY_2;

  if (!data) {
    logger.info(`缺少参数`);
    ret.msg = `缺少参数`;
    return ret;
  }

  let token = data.token;
  const orderInfo = (await Order.getOrderByToken(token))[0];
  if (!orderInfo) {
    logger.info(`订单${token}不存在`);
    ret.msg = `订单不存在`;
    return ret;
  }

  const orderId = orderInfo.order_id;
  const serverId = orderInfo.server_id;

  if (orderInfo.status == 2) {
    logger.info(`订单${token}已经重复发货`);
    ret.ret = 0;
    ret.msg = `订单${token}已经重复发货`;
    return ret;
  }

  // 验证签名
  let signData = Object.keys(data)
    .sort()
    .filter((key) => key !== "sig" && key !== "cee_extend");

  if (
    SignatureVerifier.verifyQQSign(
      "GET",
      "/api/qqCallback",
      signData,
      Key,
      data.sig
    )
  ) {
    logger.error(`${token}签名错误`);
    ret.ret = 1;
    ret.msg = `${token}签名错误`;
    return ret;
  }

  // 验证区服
  let url = await getServerList(serverId, 4);
  if (!url) {
    logger.info(`区服id错误: serverId ${serverId}`);
    ret.msg = `区服id错误: serverId ${serverId}`;
    return ret;
  }

  // 发货处理
  let orgMemId = data.openid;

  // 使用PaymentHelper发货
  const modifiedOrderInfo = {
    ...orderInfo,
    uid: orgMemId,
    server_id: serverId,
  };

  logger.info(`QQ支付订单${orderId}通知游戏发货开始`);
  const result = await PaymentHelper.deliverOrder(
    modifiedOrderInfo,
    ctx.request.ip,
    url,
    token
  );
  logger.info(`QQ支付订单${orderId}通知游戏发货结束`);

  // 转换返回格式
  return {
    ret: result.code == 1 ? 0 : 1,
    msg: result.msg,
  };
};

/**
 * 获取服务器IP地址
 * 使用多种方法尝试获取服务器的公网IP地址
 * 返回Promise，成功时解析为IP地址，失败时解析为null
 */
async function getServerIp(): Promise<string | null> {
  // 1. 首先尝试从环境变量获取服务器IP
  if (process.env.SERVER_IP) {
    logger.info("从环境变量获取到服务器IP:", process.env.SERVER_IP);
    return process.env.SERVER_IP;
  }

  // 2. 尝试使用外部API获取公网IP
  try {
    // 使用多个公共IP查询服务，提高可靠性
    const ipServices = [
      "https://api.ipify.org",
      "https://ifconfig.me/ip",
      "https://icanhazip.com",
    ];

    // 尝试从第一个可用的服务获取IP
    for (const service of ipServices) {
      try {
        const response = await axios.get(service, { timeout: 3000 });
        if (response.data && typeof response.data === "string") {
          const ip = response.data.trim();
          logger.info(`从${service}获取到服务器公网IP:`, ip);
          return ip;
        }
      } catch (err) {
        // 如果一个服务失败，尝试下一个
        continue;
      }
    }
  } catch (error) {
    logger.error("通过外部API获取公网IP失败:", error);
  }

  // 3. 尝试从网络接口获取
  try {
    const networkInterfaces = os.networkInterfaces();

    // 首先尝试查找名为eth0的接口（常见的主网络接口名称）
    if (networkInterfaces.eth0) {
      for (const iface of networkInterfaces.eth0) {
        if (!iface.internal && iface.family === "IPv4") {
          logger.info("从eth0网络接口获取到IP:", iface.address);
          return iface.address;
        }
      }
    }

    // 如果没有找到eth0，遍历所有接口
    for (const interfaceName in networkInterfaces) {
      const interfaces = networkInterfaces[interfaceName];
      if (interfaces) {
        for (const iface of interfaces) {
          // 跳过内部IP和非IPv4地址
          if (!iface.internal && iface.family === "IPv4") {
            logger.info(`从${interfaceName}网络接口获取到IP:`, iface.address);
            return iface.address;
          }
        }
      }
    }
  } catch (error) {
    logger.error("获取网络接口信息失败:", error);
  }

  // 4. 如果以上方法都失败，返回null
  logger.error("无法获取服务器IP地址");
  return null;
}

function splitString(input: string, separator: string): string[] {
  return input.split(separator);
}

class TencentController {
  async buyGood(ctx) {
    let {
      uid,
      level,
      amount,
      role_id,
      role_name,
      product_id,
      server_id,
      pfkey,
      pf,
      product_name,
      product_desc,
      goodsurl,
      openkey,
      openid,
      channel_id,
    } = ctx.request.body;

    logger.info("buyGood params:", { params: ctx.request.body });

    if (
      !product_id ||
      !server_id ||
      !role_name ||
      !role_id ||
      !amount ||
      !uid
    ) {
      ctx.body = { code: -1, message: "参数错误,创建订单失败!!", data: "" };
      return;
    }
    const data = ctx.request.body;
    if (!SignatureVerifier.verifyMD5Sign(data, ORDER_SIGN_KEY)) {
      logger.error("签名验证失败");
      ctx.body = {
        code: -1,
        message: "签名错误,创建订单失败!!",
        data: "",
      };
      return;
    }

    const orderId = generateOrderNumber(); // 生成一个长度为8的订单号
    const create_time = formatDate(new Date());
    const res = await Order.createOrder(
      orderId,
      uid,
      level,
      amount,
      role_id,
      role_name,
      product_id,
      server_id,
      channel_id,
      create_time
    );

    if (res.affectedRows <= 0) {
      ctx.body = { code: -1, message: "创建订单失败", data: "" };
      return;
    }

    let amt = amount * 10;
    let apiParams = {
      pfkey: pfkey,
      amt: amt,
      ts: Date.now(),
      payitem: `${product_id}*${amt}*1`,
      appmode: 1,
      goodsmeta: `${product_name}*${product_desc}`,
      zoneid: 1,
      pf: pf || "qqgame",
      goodsurl: goodsurl,
      appid: QQAppId,
      openid: openid,
      openkey: openkey,
    };

    let sig = SnsSigCheck.makeSig("GET", BUY_GOODS_URL, apiParams, QQAppKey);

    apiParams["sig"] = sig;

    const queryStr = Object.entries(apiParams)
      .map(
        ([key, value]) =>
          `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
      )
      .join("&");

    let url = QQ_API_URL + BUY_GOODS_URL + "?" + queryStr;
    logger.info("buyGood url:", { url: url });

    logger.info("buyGood postData:", { postData: apiParams });

    try {
      let response = await axios.get(url);

      logger.info("buyGood 接口返回 response:", {
        data: response.data,
      });

      if (response.data.ret == 0) {
        const res = await Order.updateOrderToken(
          orderId,
          response.data.token,
          "qq"
        );
      }

      ctx.body = response.data;
    } catch (error) {
      console.log(error);
    }

    logger.info("创建订单返回结果:", { params: ctx.body });
  }

  async qqCallPay(ctx) {
    // 获取当前服务器IP
    // let serverIp = "81.70.25.61";
    let serverIp = await getServerIp();
    logger.info(`当前服务器IP:${serverIp}`);

    // 目标IP和转发服务器地址
    const targetIp = "81.70.25.61";
    const forwardServer = "123.60.62.68:3000/qqCallback";
    // let serverIp = "";

    // 判断是否为目标IP
    if (serverIp === targetIp) {
      logger.info(`检测到服务器IP为${targetIp}，转发请求到${forwardServer}`);

      try {
        // 构建转发URL，保持相同的路径
        const forwardUrl = `http://${forwardServer}`;
        logger.info(`转发请求到URL:${forwardUrl}`);

        // 获取原始请求的方法和参数
        const method = ctx.request.method;
        const queryParams = ctx.request.query;
        const bodyParams = ctx.request.body;
        let response;
        // 根据原始请求方法进行转发
        if (method === "GET") {
          logger.info("转发参数:", { queryParams: queryParams });

          response = await axios.get(forwardUrl, { params: queryParams });
        } else if (method === "POST") {
          logger.info("转发参数:", { bodyParams: bodyParams });

          response = await axios.post(forwardUrl, bodyParams, {
            params: queryParams,
          });
        } else {
          // 其他请求方法
          response = await axios({
            method: method.toLowerCase(),
            url: forwardUrl,
            params: queryParams,
            data: bodyParams,
          });
        }

        logger.info("转发请求成功，收到响应:", response.data);
        // 将转发的响应返回给客户端
        ctx.body = response.data;
      } catch (error) {
        logger.error(`转发请求到${forwardServer}失败:`, error);
        logger.info("转发失败，使用本地处理逻辑");

        // 转发失败时，回退到原有处理逻辑
        var result = await CallPayQQ(ctx);
        console.log("发货结果", result);
        ctx.body = result;
      }
    } else {
      // 非目标IP或无法获取IP，使用原有处理逻辑
      logger.info(
        `当前服务器IP${
          serverIp ? `(${serverIp})` : "(未知)"
        }不是目标IP(${targetIp})，使用本地处理逻辑`
      );
      var result = await CallPayQQ(ctx);
      console.log("发货结果", result);
      ctx.body = result;
    }
  }

  async uicFilter(ctx) {
    let body = ctx.request.body;

    logger.info("uicFilter body:", { data: body });

    let apiParams = {
      openid: body.openid,
      openkey: body.openkey,
      appid: QQAppId,
    };

    logger.info("uicFilter apiParams:", { data: apiParams });

    let sign = SnsSigCheck.makeSig("POST", UIC_FILTER_URL, apiParams, QQAppKey);

    apiParams["sig"] = sign;
    const queryStr = Object.entries(apiParams)
      .map(
        ([key, value]) =>
          `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
      )
      .join("&");

    let url = QQ_PROD_URL + UIC_FILTER_URL + "?" + queryStr;
    logger.info("uicFilter url:", { url: url });
    let postData = {
      text_list_: body.text_list_,
    };

    logger.info("uicFilter postData:", { postData: postData });

    try {
      let response = await axios.post(url, postData, {
        headers: {
          "Content-Type": "application/json",
        },
      });
      logger.info("uicFilter 接口返回 response:", { data: response.data });

      ctx.body = response.data;
    } catch (error) {
      console.log(error);
    }
  }

  async getInfo(ctx) {
    let body = ctx.request.body;

    logger.info("getInfo body:", { data: body });

    let apiParams = {
      openid: body.openid,
      openkey: body.openkey,
      appid: QQAppId,
    };

    logger.info("getInfo apiParams:", { data: apiParams });

    let sign = SnsSigCheck.makeSig("GET", GET_INFO_URL, apiParams, QQAppKey);

    apiParams["sig"] = sign;
    const queryStr = Object.entries(apiParams)
      .map(
        ([key, value]) =>
          `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
      )
      .join("&");

    let url = QQ_PROD_URL + GET_INFO_URL + "?" + queryStr;
    logger.info("getInfo url:", { url: url });
    let postData = {
      text_list_: body.text_list_,
    };

    logger.info("getInfo postData:", { postData: postData });

    try {
      let response = await axios.get(url);
      logger.info("getInfo 接口返回 response:", { data: response.data });

      ctx.body = response.data;
    } catch (error) {
      console.log(error);
    }
  }

  async isLogin(ctx) {
    let body = ctx.request.body;

    logger.info("isLogin body:", { data: body });

    let ip = getClientIp(ctx);

    let apiParams = {
      openid: body.openid,
      openkey: body.openkey,
      appid: QQAppId,
      pf: body.pf,
      format: "json",
      userip: ip,
    };

    logger.info("isLogin apiParams:", { data: apiParams });

    let sign = SnsSigCheck.makeSig("GET", IS_LOGIN_URL, apiParams, QQAppKey);

    apiParams["sig"] = sign;
    const queryStr = Object.entries(apiParams)
      .map(
        ([key, value]) =>
          `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
      )
      .join("&");

    let url = QQ_PROD_URL + IS_LOGIN_URL + "?" + queryStr;
    logger.info("isLogin url:", { url: url });
    let postData = {
      text_list_: body.text_list_,
    };

    logger.info("isLogin postData:", { postData: postData });

    try {
      let response = await axios.get(url);
      logger.info("isLogin 接口返回 response:", { data: response.data });

      ctx.body = response.data;
    } catch (error) {
      console.log(error);
    }
  }

  async qqServerList(ctx) {
    let tag = ctx.query.tag || 4;
    let ip = getClientIp(ctx);

    logger.info("qqServerList 区服接口", { ip: ip });
    const servers = await Server.getAllServerList(tag, ip);
    let data = {
      ret: 0,
      msg: "success",
      recentServer: [],
      recommendServer: [],
      allServer: [],
    };

    let allServer = [];
    let recentServer = [];
    let recommendServer = [];

    servers.forEach((server) => {
      allServer.push({
        serverid: String(server.sid),
        serverName: String(server.name),
        startTime: parseInt(server.open_time),
        status: parseInt(server.status),
        actArray: [],
      });
    });

    if (allServer.length > 0) {
      recentServer = allServer.slice(-2);
    }

    data.allServer = allServer;
    data.recentServer = recentServer;
    data.recommendServer = recommendServer;

    logger.info("qqServerList 返回 response:", { data: data });

    ctx.body = data;
  }

  async qqRoleList(ctx) {
    let body = ctx.request.query;
    let data = {
      openid: body.openid,
      serverId: body.serverid,
    };

    logger.info("qqRoleList 腾讯请求参数:", { body: body });

    let port = 8004;
    let host = "123.60.62.68";
    let url = "http://" + host + ":" + port + "/api/roleList/check";

    logger.info("qqRoleList url:", { url: url });

    try {
      const response = await axios.post(url, data, {
        headers: {
          "Content-Type": "application/json",
        },
      });

      logger.info("qqServerList 返回 response:", { data: response.data });

      ctx.body = response.data;
    } catch (error) {
      console.log(error);
    }
  }

  async qqGift(ctx) {
    let body = ctx.request.query;

    logger.info("qqGift 请求参数:", { data: body });

    let data = {
      code: body.giftid,
      userId: body.roleid,
    };

    let signData = Object.keys(body)
      .sort()
      .filter((key) => key !== "sig" && key !== "cee_extend");

    if (
      SignatureVerifier.verifyQQSign(
        "GET",
        "/api/qqGift",
        signData,
        QQAppKey,
        body.sig
      )
    ) {
      logger.error(`礼包发货签名错误`);
      ctx.body = {
        ret: 1,
        msg: `签名错误`,
      };
      return;
    }

    logger.info("api cdk 接口请求 data:", { data: data });

    let serverUrl = await getServerList(body.serverid, 4);
    if (!serverUrl) {
      ctx.body = {
        ret: 1,
        msg: `区服id错误: serverId ${body.serverid}`,
      };
      return;
    }
    let port = 8004;
    let host = "123.60.62.68";
    let url = "http://" + host + ":" + port + "/api/giftCode/exchange";

    try {
      const response = await axios.post(url, data, {
        headers: {
          "Content-Type": "application/json",
        },
      });
      let param: string = "";
      logger.info("api cdk 接口返回 response:", { data: response.data });
      if (response.data.code != 200) {
        ctx.body = {
          ret: 1,
          msg: response.data.msg,
        };
        return;
      } else {
        const result = splitString(response.data.data, ";");
        // 重构itemList
        let itemList = Array();
        for (let i = 0; i < result.length; i++) {
          let elem = splitString(result[i], ":");
          let output0 = parseInt(elem[0], 10);
          let output1 = parseInt(elem[1], 10);
          itemList.push([output0, output1]);
        }
        param = JSON.stringify({
          type: "UseCDKV2",
          itemList: itemList,
          channel_id: 4,
        });
      }
      let sendMsg = new Msg();
      sendMsg.connect(serverUrl, Account);
      logger.info("通知服务器参数以及地址:", {
        param: param,
        serverUrl: serverUrl,
      });
      new Promise((resolve) => {
        setTimeout(async () => {
          sendMsg.CG_TEST_PROTO(body.account, param, body.serverId);
        }, 1000);
      });
    } catch (error) {
      console.log(error);
    }
    ctx.body = {
      ret: 0,
      msg: "success",
    };
  }

  async qqReport(ctx) {
    logger.info("qqReport params:", { params: ctx.request.body });
    const postData = ctx.request.body;

    if (!postData) {
      ctx.body = {
        ret: 1,
        msg: `参数错误`,
      };
    }

    let ip = getClientIp(ctx);

    const randomString1 = Math.floor(Math.random() * 1090000000800)
      .toString()
      .slice(0, 4);

    const log_fields_data = {
      dtEventTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
      iversion: "1.0",
      appid: QQAppId,
      userip: ip,
      svrip: ip,
      time: Date.now(),
      domain: "10",
      iworldid: 1,
      optype: 3,
      actionid: postData.actionid,
      opuid: postData.roleid,
      opopenid: postData.openid,
      level: postData.level,
      source: "qqgame_index",
      onlinetime: postData.onlinetime,
    };

    const log_fields = Object.entries(log_fields_data)
      .map(([key, value]) => `${key}=${value}`)
      .join("&");

    const data = [];
    data.push({
      log_name: "log_common",
      log_fields: log_fields,
    });

    const jsonParams = {
      title: {
        timestamp: Date.now(),
        app_id: QQAppId,
        retry_times: "0",
        app_name: "qqgame",
        seq_id: randomString1 + Date.now(),
      },
      data: data,
    };

    const apiParams = JSON.parse(JSON.stringify(jsonParams));

    logger.info("qqReport apiParams:", { jsonParams: jsonParams });

    const signStr = JSON.stringify(jsonParams) + REPORT_KEY;
    const sign = CryptoJS.MD5(signStr).toString();

    logger.info("qqReport 签名源串: " + signStr);

    try {
      const response = await axios.post(REPORT_URL, apiParams, {
        headers: {
          "Content-Type": "application/json",
          signature: sign,
          version: 1.0,
        },
      });

      logger.info("qqReport 接口返回 response:", {
        data: response.data,
      });

      ctx.body = response.data;
    } catch (error) {
      console.log(error);
    }
  }

  async getBlueVipInfo(ctx) {
    let body = ctx.request.body;

    logger.info("getBlueVipInfo body:", { data: body });

    let apiParams = {
      openid: body.openid,
      openkey: body.openkey,
      appid: QQAppId,
    };

    logger.info("getBlueVipInfo apiParams:", { data: apiParams });

    let sign = SnsSigCheck.makeSig(
      "GET",
      BLUE_VIP_INFO_URL,
      apiParams,
      QQAppKey
    );

    apiParams["sig"] = sign;
    const queryStr = Object.entries(apiParams)
      .map(
        ([key, value]) =>
          `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
      )
      .join("&");

    let url = QQ_PROD_URL + BLUE_VIP_INFO_URL + "?" + queryStr;
    logger.info("getBlueVipInfo url:", { url: url });
    let postData = {
      text_list_: body.text_list_,
    };

    logger.info("getBlueVipInfo postData:", { postData: postData });

    try {
      let response = await axios.get(url);
      logger.info("getBlueVipInfo 接口返回 response:", { data: response.data });

      ctx.body = response.data;
    } catch (error) {
      console.log(error);
    }
  }

  async getDaWanKaInfo(ctx) {
    let body = ctx.request.body;

    logger.info("getDaWanKaInfo body:", { data: body });

    let apiParams = {
      openid: body.openid,
      openkey: body.openkey,
      appid: QQAppId,
      version: 2,
      pf: body.pf,
    };

    logger.info("getDaWanKaInfo apiParams:", { data: apiParams });

    let sign = SnsSigCheck.makeSig("GET", DA_WAN_KA_URL, apiParams, QQAppKey);

    apiParams["sig"] = sign;
    const queryStr = Object.entries(apiParams)
      .map(
        ([key, value]) =>
          `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
      )
      .join("&");

    let url = QQ_PROD_URL + DA_WAN_KA_URL + "?" + queryStr;
    logger.info("getDaWanKaInfo url:", { url: url });
    let postData = {
      text_list_: body.text_list_,
    };

    logger.info("getDaWanKaInfo postData:", { postData: postData });

    try {
      let response = await axios.get(url);
      logger.info("getDaWanKaInfo 接口返回 response:", { data: response.data });

      ctx.body = response.data;
    } catch (error) {
      console.log(error);
    }
  }

  async reportDaWanKaPay(ctx) {
    let body = ctx.request.body;

    logger.info("reportDaWanKaPay body:", { data: body });

    let apiParams = {
      openid: body.openid,
      openkey: body.openkey,
      appid: QQAppId,
    };

    logger.info("reportDaWanKaPay apiParams:", { data: apiParams });

    let sign = SnsSigCheck.makeSig(
      "GET",
      DA_WAN_KA_PAY_URL,
      apiParams,
      QQAppKey
    );

    apiParams["sig"] = sign;
    const queryStr = Object.entries(apiParams)
      .map(
        ([key, value]) =>
          `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
      )
      .join("&");

    let url = QQ_PROD_URL + DA_WAN_KA_PAY_URL + "?" + queryStr;
    logger.info("reportDaWanKaPay url:", { url: url });
    let postData = {
      text_list_: body.text_list_,
    };

    logger.info("reportDaWanKaPay postData:", { postData: postData });

    try {
      let response = await axios.get(url);
      logger.info("reportDaWanKaPay 接口返回 response:", {
        data: response.data,
      });

      ctx.body = response.data;
    } catch (error) {
      console.log(error);
    }
  }
}

module.exports = new TencentController();
