// TQAPI数据源实现 - 使用Python服务
import { DataSource } from './DataSource';
import { logger } from '../../utils/logger';

// 简化的HTTP客户端
class HttpClient {
  private baseUrl: string;

  constructor(baseUrl: string) {
    this.baseUrl = baseUrl;
  }

  async get<T>(endpoint: string, params?: Record<string, string>): Promise<T> {
    let url = `${this.baseUrl}${endpoint}`;
    if (params) {
      const queryString = new URLSearchParams(params).toString();
      url += `?${queryString}`;
    }

    logger.log('发送GET请求:', url);

    try {
      // 设置20秒超时
      const controller = new AbortController();
      const timeoutId = setTimeout(() => {
        logger.error('GET请求超时，正在中止请求...');
        controller.abort();
      }, 20000);
      
      try {
        logger.log('正在发送GET请求...');
        const start = Date.now();
        const response = await fetch(url, {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json'
          },
          signal: controller.signal
        });
        const end = Date.now();
        logger.log(`GET请求完成，耗时: ${end - start}ms`);
        logger.log('GET请求响应状态:', response.status);

        if (!response.ok) {
          const errorText = await response.text();
          logger.error('GET请求失败:', errorText);
          throw new Error(`HTTP error! status: ${response.status}, message: ${errorText}`);
        }

        logger.log('正在解析GET响应数据...');
        const data = await response.json();
        logger.log('GET请求响应数据:', data);
        return data as T;
      } finally {
        clearTimeout(timeoutId);
      }
    } catch (error: any) {
      logger.error('GET请求网络错误:', error.message || error);
      logger.error('错误详情:', error);
      logger.error('错误堆栈:', error.stack);
      throw new Error(`网络请求失败: ${error.message || error}`);
    }
  }

  async post<T>(endpoint: string, data?: any): Promise<T> {
    const url = `${this.baseUrl}${endpoint}`;
    logger.log(`发送POST请求: ${url} 数据: ${JSON.stringify(data)}`);

    try {
      // 设置20秒超时
      const controller = new AbortController();
      const timeoutId = setTimeout(() => {
        logger.error('POST请求超时，正在中止请求...');
        controller.abort();
      }, 20000);
      
      try {
        logger.log('正在发送请求...');
        const start = Date.now();
        const response = await fetch(url, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: data ? JSON.stringify(data) : undefined,
          signal: controller.signal
        });
        const end = Date.now();
        logger.log(`请求完成，耗时: ${end - start}ms`);
        logger.log('POST请求响应状态:', response.status);

        if (!response.ok) {
          const errorText = await response.text();
          logger.error('POST请求失败:', errorText);
          throw new Error(`HTTP error! status: ${response.status}, message: ${errorText}`);
        }

        logger.log('正在解析响应数据...');
        const responseData = await response.json();
        logger.log('POST请求响应数据:', responseData);
        return responseData as T;
      } finally {
        clearTimeout(timeoutId);
      }
    } catch (error: any) {
      logger.error('POST请求网络错误:', error.message || error);
      logger.error('错误详情:', error);
      logger.error('错误堆栈:', error.stack);
      throw new Error(`网络请求失败: ${error.message || error}`);
    }
  }
}

export class TQDataSource implements DataSource {
  private httpClient: HttpClient;
  private initialized: boolean = false;
  private config: {
    username?: string;
    password?: string;
    timeout?: number;
    retries?: number;
    maxConnections?: number;
    pythonServiceUrl?: string;
  };

  constructor(config: any = {}) {
    logger.log('使用TQAPI数据源初始化...');
    // 从配置中读取端口，默认8001
    const port = config.pythonPort || 8001;
    this.config = {
      username: config.username || '',
      password: config.password || '',
      timeout: config.timeout || 30000,
      retries: config.retries || 3,
      maxConnections: config.maxConnections || 5,
      pythonServiceUrl: config.pythonServiceUrl || `http://127.0.0.1:${port}/api`
    };
    logger.log('TQAPI数据源配置:', this.config);
    // 测试Python服务URL是否正确
    logger.log('测试Python服务URL:', this.config.pythonServiceUrl);
    this.httpClient = new HttpClient(this.config.pythonServiceUrl!);
  }

  async initialize(): Promise<boolean> {
    try {
      logger.log('开始初始化TQAPI数据源...');
      logger.log('Python服务URL:', this.config.pythonServiceUrl);
      logger.log('连接参数:', {
        username: this.config.username ? '***' : '',
        password: this.config.password ? '***' : ''
      });
      
      // 先测试Python服务是否可达
      logger.log('测试Python服务是否可达...');
      try {
        const testUrl = `${this.config.pythonServiceUrl}/../health`;
        logger.log('测试URL:', testUrl);
        // 使用AbortController设置超时
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), 10000);
        try {
          const testResponse = await fetch(testUrl, {
            method: 'GET',
            signal: controller.signal
          });
          logger.log('Python服务健康检查响应:', testResponse.status);
          if (testResponse.ok) {
            logger.log('Python服务可达');
          } else {
            logger.error('Python服务不可达，状态码:', testResponse.status);
          }
        } finally {
          clearTimeout(timeoutId);
        }
      } catch (error: any) {
        logger.error('Python服务健康检查失败:', error.message || error);
      }
      
      // 连接到天勤服务器
      logger.log('连接到天勤服务器...');
      
      try {
        const response = await this.httpClient.post<any>('/connect', {
          username: this.config.username,
          password: this.config.password
        });
        
        logger.log('连接响应:', response);
        
        if (response.success) {
          logger.log('TQAPI连接成功');
          this.initialized = true;
          return true;
        } else {
          logger.error('TQAPI连接失败:', response.message);
          this.initialized = false;
          return false;
        }
      } catch (error: any) {
        logger.error('连接请求失败:', error.message || error);
        logger.error('错误详情:', error);
        throw error;
      }
    } catch (error) {
      logger.error('TQAPI数据源初始化失败:', error);
      this.initialized = false;
      return false;
    }
  }

  async getContractList(): Promise<any[]> {
    if (!this.initialized) {
      throw new Error('TQAPI数据源未初始化');
    }

    try {
      logger.log('获取合约列表...');
      const response = await this.httpClient.get<any>('/contracts');
      
      if (response.success && Array.isArray(response.data)) {
        logger.log('获取合约列表成功，数量:', response.data.length);
        return response.data;
      } else {
        logger.error('获取合约列表失败:', response.message);
        return [];
      }
    } catch (error) {
      logger.error('获取合约列表失败:', error);
      throw error;
    }
  }

  async getContractDetail(symbol: string): Promise<any> {
    if (!this.initialized) {
      throw new Error('TQAPI数据源未初始化');
    }

    try {
      logger.log(`获取合约${symbol}详情...`);
      const response = await this.httpClient.get<any>(`/contract/${symbol}`);
      
      if (response.success) {
        logger.log(`获取合约${symbol}详情成功`);
        return response.data;
      } else {
        logger.error(`获取合约${symbol}详情失败:`, response.message);
        throw new Error(`获取合约${symbol}详情失败`);
      }
    } catch (error) {
      logger.error(`获取合约${symbol}详情失败:`, error);
      throw error;
    }
  }

  async getKlineData(symbol: string, period: string, count: number): Promise<any[]> {
    if (!this.initialized) {
      throw new Error('TQAPI数据源未初始化');
    }

    try {
      logger.log('开始获取K线数据:', {
        symbol: symbol,
        period: period,
        count: count
      });
      
      // 确保合约代码格式正确
      let contractSymbol = symbol;
      if (!contractSymbol.includes('.')) {
        // 如果没有交易所前缀，尝试添加默认交易所
        logger.warn('合约代码缺少交易所前缀，尝试添加默认交易所');
        contractSymbol = `SHFE.${contractSymbol}`;
      }
      logger.log('使用的合约代码:', contractSymbol);
      
      const response = await this.httpClient.get<any>('/klines/' + contractSymbol, {
        period: period,
        count: count.toString()
      });
      
      if (response.success && Array.isArray(response.data)) {
        logger.log('获取K线数据成功，长度:', response.data.length);
        return response.data;
      } else {
        logger.error('获取K线数据失败:', response.message);
        return [];
      }
    } catch (error) {
      logger.error(`获取合约${symbol}K线数据失败:`, error);
      throw error;
    }
  }

  async getTickData(symbol: string): Promise<any> {
    if (!this.initialized) {
      throw new Error('TQAPI数据源未初始化');
    }

    try {
      logger.log(`获取合约${symbol}实时行情数据...`);
      
      // 确保合约代码格式正确
      let contractSymbol = symbol;
      if (!contractSymbol.includes('.')) {
        // 如果没有交易所前缀，尝试添加默认交易所
        logger.warn('合约代码缺少交易所前缀，尝试添加默认交易所');
        contractSymbol = `SHFE.${contractSymbol}`;
      }
      logger.log('使用的合约代码:', contractSymbol);
      
      logger.log('正在发送GET请求到:', `/tick/${contractSymbol}`);
      const start = Date.now();
      const response = await this.httpClient.get<any>(`/tick/${contractSymbol}`);
      const end = Date.now();
      logger.log(`GET请求完成，耗时: ${end - start}ms`);
      logger.log('响应数据:', response);
      
      if (response.success) {
        logger.log(`获取合约${symbol}实时行情数据成功`);
        // 计算价格变化
        const tickData = response.data;
        tickData.price_change = tickData.last_price - (tickData.pre_close || 0);
        logger.log('计算价格变化后的数据:', tickData);
        return tickData;
      } else {
        logger.error(`获取合约${symbol}实时行情数据失败:`, response.message);
        // 返回默认数据，避免整个请求失败
        return {
          last_price: 0,
          pre_close: 0,
          open: 0,
          high: 0,
          low: 0,
          volume: 0,
          open_interest: 0,
          bid_price1: 0,
          bid_volume1: 0,
          ask_price1: 0,
          ask_volume1: 0,
          price_change: 0,
          datetime: Date.now()
        };
      }
    } catch (error) {
      logger.error(`获取合约${symbol}实时行情数据失败:`, error);
      // 返回默认数据，避免整个请求失败
      return {
        last_price: 0,
        pre_close: 0,
        open: 0,
        high: 0,
        low: 0,
        volume: 0,
        open_interest: 0,
        bid_price1: 0,
        bid_volume1: 0,
        ask_price1: 0,
        ask_volume1: 0,
        price_change: 0,
        datetime: Date.now()
      };
    }
  }

  async getMarketOverview(): Promise<any[]> {
    if (!this.initialized) {
      throw new Error('TQAPI数据源未初始化');
    }

    try {
      // 获取所有合约
      const contracts = await this.getContractList();
      // 限制获取的合约数量，避免请求过多
      const limitedContracts = contracts.slice(0, 20);
      // 获取每个合约的实时行情
      const overview = [];
      for (const contract of limitedContracts) {
        try {
          const tick = await this.getTickData(contract.symbol);
          // 确保所有值都是有效的数字
          const price = typeof tick.last_price === 'number' ? tick.last_price : 0;
          const change = typeof tick.price_change === 'number' ? tick.price_change : 0;
          const pre_close = typeof tick.pre_close === 'number' && tick.pre_close !== 0 ? tick.pre_close : 1;
          const volume = typeof tick.volume === 'number' ? tick.volume : 0;
          const open_interest = typeof tick.open_interest === 'number' ? tick.open_interest : 0;
          
          overview.push({
            symbol: contract.symbol,
            name: contract.name,
            price: price,
            change: change,
            change_percent: change / pre_close * 100,
            volume: volume,
            open_interest: open_interest
          });
        } catch (error) {
          logger.error(`获取合约${contract.symbol}行情失败:`, error);
        }
      }
      return overview;
    } catch (error) {
      logger.error('获取市场概览失败:', error);
      throw error;
    }
  }

  async getHistoricalTrades(symbol: string, start: number, end: number): Promise<any[]> {
    if (!this.initialized) {
      throw new Error('TQAPI数据源未初始化');
    }

    try {
      // 目前Python服务未实现此功能
      logger.warn('TQAPI服务暂未实现历史成交数据获取功能');
      return [];
    } catch (error) {
      logger.error(`获取合约${symbol}历史成交数据失败:`, error);
      throw error;
    }
  }

  async close(): Promise<void> {
    try {
      logger.log('关闭TQAPI连接...');
      const response = await this.httpClient.post<any>('/disconnect');
      
      if (response.success) {
        logger.log('TQAPI连接已关闭');
      } else {
        logger.error('关闭TQAPI连接失败:', response.message);
      }
    } catch (error) {
      logger.error('关闭TQAPI连接失败:', error);
    } finally {
      this.initialized = false;
      logger.log('TQAPI数据源已关闭');
    }
  }
}