import axios, { AxiosInstance } from 'axios';
import { createHash } from 'crypto';
import { FeieApiConfig, FeiePrinterInfo, FeiePrintRequest, FeiePrintResponse, FeiePrinterStatusResponse, FeieOrderStatusResponse, FeieAddPrinterResponse, FeieDeletePrinterResponse } from '../types/feie.types';

export class FeieApiService {
  private client: AxiosInstance;
  private config: FeieApiConfig;
  private maxRetries: number;

  constructor(config: FeieApiConfig) {
    // 确保baseUrl有默认值
    const defaultBaseUrl = 'https://api.feieyun.cn/Api/Open/';

    this.config = {
      baseUrl: defaultBaseUrl,
      timeout: 30000, // 增加到30秒，飞鹅API有时响应较慢
      maxRetries: 3,
      ...config
    };

    this.maxRetries = this.config.maxRetries || 3;

    this.client = axios.create({
      baseURL: this.config.baseUrl,
      timeout: this.config.timeout,
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      }
    });
  }

  /**
   * 生成飞鹅API签名
   */
  private generateSignature(timestamp: number): string {
    const content = `${this.config.user}${this.config.ukey}${timestamp}`;
    return createHash('sha1').update(content).digest('hex');
  }

  /**
   * 解析飞鹅API返回的响应（支持JSON和PHP var_dump格式）
   */
  private parseFeieResponse(responseString: string): any {
    try {
      console.debug('开始解析飞鹅API响应');

      // 移除多余的空白字符和换行
      const cleaned = responseString.trim();
      console.debug('清理后的响应:', cleaned.substring(0, 200) + '...');

      // 首先尝试解析为JSON
      try {
        const jsonResult = JSON.parse(cleaned);
        console.debug('成功解析为JSON格式');
        return jsonResult;
      } catch (jsonError) {
        console.debug('不是JSON格式，尝试解析PHP var_dump格式');
      }

      // 检查是否是var_dump格式
      if (!cleaned.startsWith('array(')) {
        console.debug('不是PHP var_dump格式');
        return null;
      }

      // 解析PHP var_dump格式
      const result: any = {};

      // 提取ret字段 - 支持多种格式
      let retMatch = cleaned.match(/\["ret"\]\s*=>\s*int\((\d+)\)/);
      if (!retMatch) {
        retMatch = cleaned.match(/\["ret"\]\s*=>\s*string\((\d+)\)\s*"(\d+)"/);
        if (retMatch) {
          result.ret = parseInt(retMatch[2], 10);
        }
      } else {
        result.ret = parseInt(retMatch[1], 10);
      }

      // 提取msg字段
      const msgMatch = cleaned.match(/\["msg"\]\s*=>\s*string\((\d+)\)\s*"([^"]*)"/);
      if (msgMatch) {
        result.msg = msgMatch[2];
      }

      // 提取data字段中的信息
      const dataMatch = cleaned.match(/\["data"\]\s*=>\s*array\(\d+\)\s*{([\s\S]*?)}\s*}/);
      if (dataMatch) {
        const dataContent = dataMatch[1];
        result.data = {};

        // 提取ok数组
        const okMatch = dataContent.match(/\["ok"\]\s*=>\s*array\(\d+\)\s*{([\s\S]*?)}/);
        if (okMatch) {
          result.data.ok = [];
          const okContent = okMatch[1];
          const okItems = okContent.match(/\[(\d+)\]\s*=>\s*string\(\d+\)\s*"([^"]*)"/g);
          if (okItems) {
            okItems.forEach(item => {
              const itemMatch = item.match(/string\(\d+\)\s*"([^"]*)"/);
              if (itemMatch) {
                result.data.ok.push(itemMatch[1]);
              }
            });
          }
        }

        // 提取no数组
        const noMatch = dataContent.match(/\["no"\]\s*=>\s*array\(\d+\)\s*{([\s\S]*?)}/);
        if (noMatch) {
          result.data.no = [];
          const noContent = noMatch[1];
          const noItems = noContent.match(/\[(\d+)\]\s*=>\s*string\(\d+\)\s*"([^"]*)"/g);
          if (noItems) {
            noItems.forEach(item => {
              const itemMatch = item.match(/string\(\d+\)\s*"([^"]*)"/);
              if (itemMatch) {
                result.data.no.push(itemMatch[1]);
              }
            });
          }
        }
      }

      // 如果没有解析到ret字段，尝试其他方式
      if (result.ret === undefined) {
        console.debug('未解析到ret字段，尝试其他方式');
        // 检查是否有错误信息
        if (cleaned.includes('错误：')) {
          result.ret = -1; // 假设是参数错误
          result.msg = '打印机添加失败';
        } else if (cleaned.includes('"ok"')) {
          result.ret = 0;
          result.msg = 'ok';
        }
      }

      console.debug('解析结果:', JSON.stringify(result, null, 2));
      return result;
    } catch (error) {
      console.debug('解析飞鹅API响应失败:', error);
      return null;
    }
  }

  /**
   * 执行API请求，支持重试
   */
  private async executeRequest<T>(endpoint: string, params: Record<string, any>): Promise<T> {
    const timestamp = Math.floor(Date.now() / 1000);
    const signature = this.generateSignature(timestamp);

    const requestParams = {
      user: this.config.user,
      stime: timestamp,
      sig: signature,
      apiname: endpoint,  // 飞鹅API要求将接口名作为apiname参数传递
      debug: 1,  // 添加debug参数以便查看更多错误信息
      ...params
    };

    // 调试日志：记录请求信息（不记录敏感信息）
    console.debug(`飞鹅API请求: ${endpoint}, 用户: ${this.config.user}, 时间戳: ${timestamp}`);

    let lastError: Error | null = null;

    for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
      try {
        // 飞鹅API所有请求都发送到根路径，接口名通过apiname参数指定
        const response = await this.client.post('', requestParams);

        // 调试日志：记录完整的API响应
        console.debug(`飞鹅API响应:`, {
          status: response.status,
          statusText: response.statusText,
          data: response.data,
          headers: response.headers
        });

        // 检查响应数据结构
        if (!response.data) {
          throw new Error(`飞鹅API响应格式错误: 响应数据为空`);
        }

        // 尝试解析响应数据，可能是字符串或对象
        let responseData = response.data;

        // 如果是字符串，使用统一的解析函数
        if (typeof responseData === 'string') {
          const parsedResponse = this.parseFeieResponse(responseData);
          if (parsedResponse) {
            responseData = parsedResponse;
          } else {
            // 检查是否是HTML错误页面
            if (responseData.includes('<!DOCTYPE') || responseData.includes('<html')) {
              throw new Error(`飞鹅API返回HTML错误页面，可能是网络或配置问题: ${responseData.substring(0, 200)}...`);
            }
            throw new Error(`飞鹅API响应格式错误: 无法解析响应数据: ${responseData.substring(0, 200)}...`);
          }
        }

        // 检查是否为对象
        if (typeof responseData !== 'object' || responseData === null) {
          throw new Error(`飞鹅API响应格式错误: 响应数据不是有效的对象: ${JSON.stringify(responseData)}`);
        }

        // 检查ret字段是否存在
        if (responseData.ret === undefined) {
          // 飞鹅API有时会返回不同的字段名，检查常见字段
          if (responseData.code !== undefined) {
            // 如果有code字段，将其映射到ret
            responseData.ret = responseData.code;
          } else if (responseData.error !== undefined) {
            // 如果有error字段，将其作为错误信息
            throw new Error(`飞鹅API错误: ${responseData.error}`);
          } else if (responseData.msg !== undefined) {
            // 如果只有msg字段，将其作为错误信息，并设置ret为-1（参数错误）
            responseData.ret = -1;
            console.debug('飞鹅API响应缺少ret字段，但包含msg字段，设置为参数错误:', responseData.msg);
          } else {
            throw new Error(`飞鹅API响应格式错误: 缺少ret字段，响应数据: ${JSON.stringify(responseData)}`);
          }
        }

        if (responseData.ret !== 0) {
          const errorMsg = responseData.msg || '未知错误';
          const errorCode = responseData.ret;

          // 根据错误代码提供更详细的错误信息
          let detailedMessage = `飞鹅API错误: ${errorMsg} (错误代码: ${errorCode})`;

          // 常见的飞鹅API错误代码
          switch (errorCode) {
            case -1:
              detailedMessage += ' - 参数错误，请检查请求参数';
              break;
            case -2:
              detailedMessage += ' - 签名错误，请检查用户和密钥配置';
              break;
            case -3:
              detailedMessage += ' - 用户或密钥错误';
              break;
            case -4:
              detailedMessage += ' - 打印机不存在或未授权';
              break;
            case -5:
              detailedMessage += ' - 打印机离线';
              break;
            case -6:
              detailedMessage += ' - 订单号重复';
              break;
            case -7:
              detailedMessage += ' - 打印内容过长';
              break;
            case -8:
              detailedMessage += ' - 请求频率过高';
              break;
            case -9:
              detailedMessage += ' - 打印机忙';
              break;
            case -10:
              detailedMessage += ' - 打印机缺纸';
              break;
            case -11:
              detailedMessage += ' - 打印机过热';
              break;
            case -12:
              detailedMessage += ' - 打印机故障';
              break;
            default:
              detailedMessage += ' - 未知API错误';
          }

          throw new Error(detailedMessage);
        }

        return responseData;
      } catch (error) {
        lastError = error as Error;

        // 如果是 Axios 错误，提供更详细的信息
        if (axios.isAxiosError(error)) {
          const status = error.response?.status;
          const data = error.response?.data;

          let axiosErrorMsg = `HTTP错误: ${status || '未知'}`;

          if (status === 400) {
            axiosErrorMsg += ' - 请求参数错误';
            if (data && typeof data === 'object') {
              axiosErrorMsg += `, 响应: ${JSON.stringify(data)}`;
            }
          } else if (status === 401) {
            axiosErrorMsg += ' - 认证失败';
          } else if (status === 403) {
            axiosErrorMsg += ' - 权限不足';
          } else if (status === 404) {
            axiosErrorMsg += ' - API端点不存在';
          } else if (status === 429) {
            axiosErrorMsg += ' - 请求频率过高';
          } else if (status && status >= 500) {
            axiosErrorMsg += ' - 服务器内部错误';
          }

          lastError = new Error(`飞鹅API请求失败: ${axiosErrorMsg}`);
        }

        if (attempt < this.maxRetries) {
          // 等待指数退避
          const delay = Math.pow(2, attempt) * 1000;
          await new Promise(resolve => setTimeout(resolve, delay));
          continue;
        }
      }
    }

    throw lastError || new Error('飞鹅API请求失败');
  }

  /**
   * 添加打印机
   */
  async addPrinter(printerInfo: FeiePrinterInfo): Promise<FeieAddPrinterResponse> {
    const { sn, key, name = '' } = printerInfo;

    // 如果是测试配置，返回模拟数据
    if (this.config.user === 'test_user' && this.config.ukey === 'test_ukey') {
      console.debug(`测试配置，模拟添加打印机: ${sn}`);
      return {
        ret: 0,
        msg: 'ok',
        data: {
          ok: [sn],
          no: []
        }
      };
    }

    // 飞鹅API要求格式：sn#key#remark，其中remark是备注名称
    const snlist = `${sn}#${key}#${name}`;

    return this.executeRequest<FeieAddPrinterResponse>('Open_printerAddlist', {
      printerContent: snlist
    });
  }

  /**
   * 删除打印机
   */
  async deletePrinter(sn: string): Promise<FeieDeletePrinterResponse> {
    const snlist = sn;

    return this.executeRequest<FeieDeletePrinterResponse>('Open_printerDelList', {
      snlist
    });
  }

  /**
   * 查询打印机状态
   */
  async queryPrinterStatus(sn: string): Promise<FeiePrinterStatusResponse> {
    return this.executeRequest<FeiePrinterStatusResponse>('Open_queryPrinterStatus', {
      sn
    });
  }

  /**
   * 打印小票
   */
  async printReceipt(printRequest: FeiePrintRequest): Promise<FeiePrintResponse> {
    const { sn, content, times = 1 } = printRequest;

    return this.executeRequest<FeiePrintResponse>('Open_printMsg', {
      sn,
      content,
      times
    });
  }

  /**
   * 查询订单打印状态
   */
  async queryOrderStatus(orderId: string): Promise<FeieOrderStatusResponse> {
    return this.executeRequest<FeieOrderStatusResponse>('Open_queryOrderState', {
      orderid: orderId
    });
  }

  /**
   * 根据时间查询订单
   */
  async queryOrdersByDate(date: string, page: number = 1): Promise<any> {
    return this.executeRequest<any>('Open_queryOrderInfoByDate', {
      date,
      page
    });
  }

  /**
   * 批量查询打印机状态
   */
  async batchQueryPrinterStatus(snList: string[]): Promise<FeiePrinterStatusResponse> {
    const snlist = snList.join('-');

    return this.executeRequest<FeiePrinterStatusResponse>('Open_queryPrinterStatus', {
      snlist
    });
  }

  /**
   * 获取打印机在线状态
   */
  async getPrinterOnlineStatus(sn: string): Promise<boolean> {
    try {
      const response = await this.queryPrinterStatus(sn);

      if (response.data && response.data.length > 0) {
        const printerStatus = response.data[0];
        return printerStatus.online === 1;
      }

      return false;
    } catch (error) {
      console.error('获取打印机在线状态失败:', error);
      return false;
    }
  }

  /**
   * 验证打印机配置
   */
  async validatePrinterConfig(sn: string, key: string): Promise<boolean> {
    try {
      console.debug(`开始验证打印机配置，SN: ${sn}, 用户: ${this.config.user}`);

      // 如果是测试配置，直接返回true，避免调用真实API
      if (this.config.user === 'test_user' && this.config.ukey === 'test_ukey') {
        console.debug(`测试配置，跳过真实API验证`);
        return true;
      }

      // 首先尝试查询打印机状态，检查打印机是否已存在
      try {
        await this.executeRequest('Open_queryPrinterStatus', {
          sn
        });
        console.debug(`打印机 ${sn} 已存在，配置验证通过`);
        return true;
      } catch (queryError: any) {
        console.debug(`查询打印机状态失败:`, queryError.message);

        // 如果错误代码是-4（打印机不存在），尝试添加打印机来验证密钥
        // 或者错误代码是undefined（可能是响应格式错误），也尝试添加验证
        // 或者错误信息包含"响应格式错误"，也尝试添加验证
        if (queryError.message.includes('错误代码: -4') ||
            queryError.message.includes('错误代码: undefined') ||
            queryError.message.includes('响应格式错误')) {
          console.debug(`打印机 ${sn} 不存在或响应格式错误，尝试添加验证。错误信息: ${queryError.message}`);

          try {
            // 尝试添加打印机
            const addResponse = await this.executeRequest<any>('Open_printerAddlist', {
              printerContent: `${sn}#${key}#验证配置`
            });

            console.debug(`打印机添加API响应:`, JSON.stringify(addResponse, null, 2));

            // 检查响应结果
            if (addResponse.ret === 0) {
              // ret为0表示API调用成功
              // 检查data.no数组中是否包含当前打印机
              const isInNoArray = addResponse.data?.no?.some((item: string) =>
                item.includes(sn) && item.includes(key)
              );

              if (isInNoArray) {
                // 打印机在no数组中，检查具体错误
                const errorItem = addResponse.data.no.find((item: string) =>
                  item.includes(sn) && item.includes(key)
                );

                if (errorItem && errorItem.includes('已被添加过')) {
                  console.debug(`打印机 ${sn} 已被添加过，配置验证通过`);
                  return true; // 打印机已存在，配置正确
                } else if (errorItem && errorItem.includes('设备编号和KEY不正确')) {
                  console.debug(`打印机 ${sn} 设备编号和KEY不正确，配置验证失败`);
                  return false; // 配置错误
                } else {
                  console.debug(`打印机 ${sn} 添加失败，未知错误: ${errorItem}`);
                  return false;
                }
              } else {
                // 打印机添加成功或在ok数组中
                console.debug(`打印机 ${sn} 添加成功，配置验证通过，开始删除测试打印机`);

                // 删除刚刚添加的测试打印机
                try {
                  await this.executeRequest('Open_printerDelList', {
                    snlist: sn
                  });
                  console.debug('删除测试打印机成功');
                } catch (deleteError: any) {
                  console.debug('删除测试打印机失败，但配置验证已通过:', deleteError.message);
                }

                return true;
              }
            } else {
              // ret不为0，API调用失败
              console.debug(`打印机 ${sn} 添加失败，ret: ${addResponse.ret}, msg: ${addResponse.msg}`);
              return false;
            }
          } catch (addError: any) {
            console.debug(`打印机 ${sn} 添加失败:`, addError.message);

            // 如果返回-1（参数错误）、-2（签名错误）或-3（用户或密钥错误），说明配置有问题
            // 其他错误（如格式错误等）也认为配置有问题
            const isParamError = addError.message.includes('错误代码: -1') ||
                                addError.message.includes('错误代码: -2') ||
                                addError.message.includes('错误代码: -3');

            // 检查是否是响应格式错误
            const isFormatError = addError.message.includes('响应格式错误') ||
                                 addError.message.includes('无法解析响应数据') ||
                                 addError.message.includes('HTML错误页面');

            // 检查是否是超时错误
            const isTimeoutError = addError.message.includes('timeout') ||
                                  addError.message.includes('超时') ||
                                  addError.message.includes('Timeout');

            const isValid = !isParamError && !isFormatError && !isTimeoutError;
            console.debug(`配置验证结果: ${isValid ? '通过' : '失败'}, 参数错误: ${isParamError}, 格式错误: ${isFormatError}, 超时错误: ${isTimeoutError}`);

            // 如果是超时错误，可能是网络问题，建议用户检查网络连接
            if (isTimeoutError) {
              console.debug('飞鹅API请求超时，请检查网络连接或联系管理员检查飞鹅API服务状态');
            }

            return isValid;
          }
        }

        // 其他错误情况
        console.debug(`查询打印机状态失败:`, queryError.message);
        return false;
      }
    } catch (error) {
      console.error('验证打印机配置失败:', error);
      if (error instanceof Error) {
        console.error('错误详情:', error.message);
      }
      return false;
    }
  }
}