import {formatDate, getServerAddr, getServerList} from "./common";
import Msg from "./msg";
import { Account } from "../config/thirdParams";
const logger = require("../utils/log");
const Order = require("../model/OrderModel");
const User = require("../model/UserModel");

interface PaymentResult {
  code: number;
  msg: string;
}

interface OrderInfo {
  id?: number;
  order_id: string;
  uid: string;
  server_id: number;
  product_id: number;
  amount: number;
  status: number;
  channel_id: number;
}

export class PaymentHelper {
  static readonly DEFAULT_RESULT: PaymentResult = { code: 0, msg: "发货失败" };
  static readonly FAIL_RESULT: PaymentResult = { code: 0, msg: "通知服务器失败" };
  static readonly SUCCESS_RESULT: PaymentResult = { code: 1, msg: "发货成功" };

  /**
   * 验证订单基本信息
   */
  static async validateOrder(orderId: string): Promise<{
    valid: boolean;
    url?: string;
    orderInfo?: any;
    message?: string;
  }> {
    const orderInfo = (await Order.getOrder(orderId))[0];

    if (!orderInfo) {
      logger.info(`订单${orderId}不存在`);
      return { valid: false, message: `订单${orderId}不存在` };
    }

    if (orderInfo.status == 2) {
      logger.info(`订单${orderId}已经重复发货`);
      return { valid: false, message: `订单${orderId}已经重复发货` };
    }

    const url = await getServerAddr(orderInfo.server_id, orderInfo.channel_id);
    if (!url) {
      logger.info(`区服id错误: serverId ${orderInfo.server_id}`);
      return {
        valid: false,
        message: `区服id错误: serverId ${orderInfo.server_id}`,
      };
    }

    return { valid: true, url: url, orderInfo };
  }

  /**
   * 等待连接就绪（轮询检查）
   */
  private static async waitForConnection(
    sendMsg: any,
    maxWaitTime: number = 5000,
    checkInterval: number = 100
  ): Promise<boolean> {
    const startTime = Date.now();
    
    return new Promise((resolve) => {
      const checkConnection = () => {
        const elapsed = Date.now() - startTime;
        
        // 检查连接是否就绪
        if (sendMsg.isConnect === true && sendMsg.websocket?.readyState === 1) {
          logger.info("连接就绪", { elapsed: `${elapsed}ms` });
          resolve(true);
          return;
        }
        
        // 检查是否超时
        if (elapsed >= maxWaitTime) {
          logger.warn("等待连接超时", { elapsed: `${elapsed}ms`, maxWaitTime });
          resolve(false);
          return;
        }
        
        // 继续等待
        setTimeout(checkConnection, checkInterval);
      };
      
      checkConnection();
    });
  }

  /**
   * 发送游戏内消息并更新订单状态（带重试机制）
   */
  static async deliverOrder(
    orderInfo: OrderInfo,
    ip: string,
    url: string,
    out_trade_no: string
  ): Promise<PaymentResult> {
    return new Promise(async (resolve) => {
      const maxRetries = 3; // 最多重试3次
      const retryDelay = 1000; // 重试间隔1秒
      
      for (let attempt = 1; attempt <= maxRetries; attempt++) {
        try {
          logger.info(`开始第${attempt}次发货尝试`, { 
            order: orderInfo.order_id,
            url: url,
            attempt: `${attempt}/${maxRetries}`
          });
          
          const sendMsg = new Msg();
          sendMsg.connect(url, Account);

          // 等待连接就绪（最多等待5秒）
          const isConnected = await this.waitForConnection(sendMsg, 5000, 100);
          
          if (!isConnected) {
            logger.warn(`第${attempt}次连接失败`, { 
              order: orderInfo.order_id,
              isConnect: sendMsg.isConnect,
              readyState: sendMsg.websocket?.readyState
            });
            
            // 清理连接
            if (sendMsg.websocket) {
              sendMsg.close();
            }
            
            // 如果不是最后一次尝试，等待后重试
            if (attempt < maxRetries) {
              logger.info(`等待${retryDelay}ms后重试`);
              await new Promise(r => setTimeout(r, retryDelay));
              continue;
            } else {
              logger.error("所有连接尝试均失败", { order: orderInfo.order_id });
              resolve(this.FAIL_RESULT);
              return;
            }
          }

          // 构建消息参数
          const params = JSON.stringify({
            account: orderInfo.uid,
            channel_id: orderInfo.channel_id,
            order: orderInfo.order_id,
            id: orderInfo.product_id,
            cnt: 100,
            money: orderInfo.amount,
          });

          logger.info("通知游戏服务器参数", { data: params });
          logger.info("通知游戏服务器orderInfo", { orderInfo: orderInfo });
          
          // 发送消息
          let send_res = sendMsg.CG_ASK_LOGIN(
            Account,
            0,
            "",
            "cn",
            "CN",
            ip,
            params,
            orderInfo.server_id
          );

          if (!send_res) {
            logger.warn(`第${attempt}次发送消息失败`, { 
              order: orderInfo.order_id,
              isConnect: sendMsg.isConnect,
              readyState: sendMsg.websocket?.readyState
            });
            
            // 如果不是最后一次尝试，等待后重试
            if (attempt < maxRetries) {
              logger.info(`等待${retryDelay}ms后重试`);
              await new Promise(r => setTimeout(r, retryDelay));
              continue;
            } else {
              logger.error("所有发送尝试均失败", { order: orderInfo.order_id });
              resolve(this.FAIL_RESULT);
              return;
            }
          }

          logger.info(`第${attempt}次发送消息成功`, { order: orderInfo.order_id });

          // 更新订单状态
          const update_time = formatDate(new Date());
          const res = await Order.updateOrderStats(
            orderInfo.order_id,
            2,
            out_trade_no,
            update_time,
            orderInfo.uid
          );

          if (res.affectedRows <= 0) {
            logger.warn(`订单${orderInfo.order_id} 数据库更新失败`, { 
              affectedRows: res.affectedRows 
            });
            resolve(this.DEFAULT_RESULT);
            return;
          }

          logger.info(`订单${orderInfo.order_id} 发货成功`, { attempt });
          resolve(this.SUCCESS_RESULT);
          return;
          
        } catch (error) {
          logger.error(`第${attempt}次发货过程出错`, { 
            order: orderInfo.order_id,
            error: error.message || error,
            attempt: `${attempt}/${maxRetries}`
          });
          
          // 如果不是最后一次尝试，等待后重试
          if (attempt < maxRetries) {
            logger.info(`等待${retryDelay}ms后重试`);
            await new Promise(r => setTimeout(r, retryDelay));
            continue;
          } else {
            logger.error("所有尝试均失败", { order: orderInfo.order_id });
            resolve(this.DEFAULT_RESULT);
            return;
          }
        }
      }
    });
  }

  /**
   * 验证签名
   */
  static verifySign(
    data: any,
    secret: string,
    excludeFields: string[] = ["sign"]
  ): boolean {
    const signData = Object.keys(data)
      .sort()
      .filter((key) => !excludeFields.includes(key));

    const signStr = signData.map((key) => `${data[key]}`).join("") + secret;
    const CryptoJS = require("crypto-js");
    const newSign = CryptoJS.MD5(signStr).toString();

    return newSign === data.sign;
  }
}
