import axios from 'axios';
import { ILLMAdapter, Message, LLMOptions, LLMResponse, StreamChunk } from './types.js';
import { config } from '../../../config/env.js';

/**
 * CloseAI通用适配器
 * 
 * 支持通过CloseAI代理访问：
 * - OpenAI GPT-5-Pro
 * - Anthropic Claude-4.5-Sonnet
 * 
 * 设计原则：
 * - CloseAI提供OpenAI兼容的统一接口
 * - 通过不同的Base URL区分供应商
 * - 代码逻辑完全复用（OpenAI标准格式）
 * 
 * 参考文档：docs/02-通用能力层/01-LLM大模型网关/03-CloseAI集成指南.md
 */
export class CloseAIAdapter implements ILLMAdapter {
  modelName: string;
  private apiKey: string;
  private baseURL: string;
  private provider: 'openai' | 'claude';

  /**
   * 构造函数
   * @param provider - 供应商类型：'openai' 或 'claude'
   * @param modelName - 模型名称（如 'gpt-5-pro' 或 'claude-sonnet-4-5-20250929'）
   */
  constructor(provider: 'openai' | 'claude', modelName: string) {
    this.provider = provider;
    this.modelName = modelName;
    this.apiKey = config.closeaiApiKey || '';
    
    // 根据供应商选择对应的Base URL
    this.baseURL = provider === 'openai'
      ? config.closeaiOpenaiBaseUrl  // https://api.openai-proxy.org/v1
      : config.closeaiClaudeBaseUrl; // https://api.openai-proxy.org/anthropic

    // 验证API Key配置
    if (!this.apiKey) {
      throw new Error(
        'CloseAI API key is not configured. Please set CLOSEAI_API_KEY in .env file.'
      );
    }

    console.log(`[CloseAIAdapter] 初始化完成`, {
      provider: this.provider,
      model: this.modelName,
      baseURL: this.baseURL,
    });
  }

  /**
   * 非流式调用
   * - OpenAI系列：使用chat.completions格式
   * - Claude系列：使用messages格式（Anthropic SDK）
   */
  async chat(messages: Message[], options?: LLMOptions): Promise<LLMResponse> {
    try {
      // Claude使用不同的API格式
      if (this.provider === 'claude') {
        return await this.chatClaude(messages, options);
      }

      // OpenAI系列：标准格式（不包含temperature等可能不支持的参数）
      const requestBody: any = {
        model: this.modelName,
        messages: messages,
        max_tokens: options?.maxTokens ?? 2000,
      };

      // 可选参数：只在提供时才添加
      if (options?.temperature !== undefined) {
        requestBody.temperature = options.temperature;
      }
      if (options?.topP !== undefined) {
        requestBody.top_p = options.topP;
      }

      console.log(`[CloseAIAdapter] 发起非流式调用`, {
        provider: this.provider,
        model: this.modelName,
        messagesCount: messages.length,
        params: Object.keys(requestBody),
      });

      const response = await axios.post(
        `${this.baseURL}/chat/completions`,
        requestBody,
        {
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${this.apiKey}`,
          },
          timeout: 180000, // 180秒超时（3分钟）- GPT-5和Claude可能需要更长时间
        }
      );

      const choice = response.data.choices[0];
      
      const result: LLMResponse = {
        content: choice.message.content,
        model: response.data.model,
        usage: {
          promptTokens: response.data.usage.prompt_tokens,
          completionTokens: response.data.usage.completion_tokens,
          totalTokens: response.data.usage.total_tokens,
        },
        finishReason: choice.finish_reason,
      };

      console.log(`[CloseAIAdapter] 调用成功`, {
        provider: this.provider,
        model: result.model,
        tokens: result.usage?.totalTokens,
        contentLength: result.content.length,
      });

      return result;
    } catch (error: unknown) {
      console.error(`[CloseAIAdapter] ${this.provider.toUpperCase()} API Error:`, error);
      
      if (axios.isAxiosError(error)) {
        const errorMessage = error.response?.data?.error?.message || error.message;
        const statusCode = error.response?.status;
        
        // 提供更友好的错误信息
        if (statusCode === 401) {
          throw new Error(
            `CloseAI认证失败: API Key无效或已过期。请检查 CLOSEAI_API_KEY 配置。`
          );
        } else if (statusCode === 429) {
          throw new Error(
            `CloseAI速率限制: 请求过于频繁，请稍后重试。`
          );
        } else if (statusCode === 500 || statusCode === 502 || statusCode === 503) {
          throw new Error(
            `CloseAI服务异常: 代理服务暂时不可用，请稍后重试。`
          );
        }
        
        throw new Error(
          `CloseAI (${this.provider.toUpperCase()}) API调用失败: ${errorMessage}`
        );
      }
      
      throw error;
    }
  }

  /**
   * Claude专用调用方法
   * 使用Anthropic Messages API格式
   */
  private async chatClaude(messages: Message[], options?: LLMOptions): Promise<LLMResponse> {
    try {
      const requestBody = {
        model: this.modelName,
        messages: messages,
        max_tokens: options?.maxTokens ?? 2000,
      };

      console.log(`[CloseAIAdapter] 发起Claude调用`, {
        model: this.modelName,
        messagesCount: messages.length,
      });

      const response = await axios.post(
        `${this.baseURL}/v1/messages`,  // Anthropic使用 /v1/messages
        requestBody,
        {
          headers: {
            'Content-Type': 'application/json',
            'x-api-key': this.apiKey,  // Anthropic使用 x-api-key 而不是 Authorization
            'anthropic-version': '2023-06-01',  // Anthropic需要版本号
          },
          timeout: 180000,
        }
      );

      // Anthropic的响应格式不同
      const content = response.data.content[0].text;
      
      const result: LLMResponse = {
        content: content,
        model: response.data.model,
        usage: {
          promptTokens: response.data.usage.input_tokens,
          completionTokens: response.data.usage.output_tokens,
          totalTokens: response.data.usage.input_tokens + response.data.usage.output_tokens,
        },
        finishReason: response.data.stop_reason,
      };

      console.log(`[CloseAIAdapter] Claude调用成功`, {
        model: result.model,
        tokens: result.usage?.totalTokens,
        contentLength: result.content.length,
      });

      return result;
    } catch (error: unknown) {
      console.error(`[CloseAIAdapter] Claude API Error:`, error);
      
      if (axios.isAxiosError(error)) {
        const errorMessage = error.response?.data?.error?.message || error.message;
        throw new Error(
          `CloseAI (Claude) API调用失败: ${errorMessage}`
        );
      }
      
      throw error;
    }
  }

  /**
   * 流式调用
   * - OpenAI系列：使用SSE格式
   * - Claude系列：暂不支持（可后续实现）
   */
  async *chatStream(
    messages: Message[],
    options?: LLMOptions,
    onChunk?: (chunk: StreamChunk) => void
  ): AsyncGenerator<StreamChunk, void, unknown> {
    // Claude流式调用暂不支持
    if (this.provider === 'claude') {
      throw new Error('Claude流式调用暂未实现，请使用非流式调用');
    }

    try {
      // OpenAI系列：标准SSE格式
      const requestBody: any = {
        model: this.modelName,
        messages: messages,
        max_tokens: options?.maxTokens ?? 2000,
        stream: true,
      };

      // 可选参数：只在提供时才添加
      if (options?.temperature !== undefined) {
        requestBody.temperature = options.temperature;
      }
      if (options?.topP !== undefined) {
        requestBody.top_p = options.topP;
      }

      console.log(`[CloseAIAdapter] 发起流式调用`, {
        provider: this.provider,
        model: this.modelName,
        messagesCount: messages.length,
      });

      const response = await axios.post(
        `${this.baseURL}/chat/completions`,
        requestBody,
        {
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${this.apiKey}`,
          },
          responseType: 'stream',
          timeout: 180000, // 180秒超时
        }
      );

      const stream = response.data;
      let buffer = '';
      let chunkCount = 0;

      for await (const chunk of stream) {
        buffer += chunk.toString();
        const lines = buffer.split('\n');
        buffer = lines.pop() || '';

        for (const line of lines) {
          const trimmedLine = line.trim();
          
          // 跳过空行和结束标记
          if (!trimmedLine || trimmedLine === 'data: [DONE]') {
            continue;
          }

          // 解析SSE数据
          if (trimmedLine.startsWith('data: ')) {
            try {
              const jsonStr = trimmedLine.slice(6);
              const data = JSON.parse(jsonStr);
              
              const choice = data.choices[0];
              const content = choice.delta?.content || '';
              
              const streamChunk: StreamChunk = {
                content: content,
                done: choice.finish_reason === 'stop',
                model: data.model,
              };

              // 如果流结束，附加usage信息
              if (choice.finish_reason === 'stop' && data.usage) {
                streamChunk.usage = {
                  promptTokens: data.usage.prompt_tokens,
                  completionTokens: data.usage.completion_tokens,
                  totalTokens: data.usage.total_tokens,
                };
              }

              chunkCount++;

              // 回调函数（可选）
              if (onChunk) {
                onChunk(streamChunk);
              }

              yield streamChunk;
            } catch (parseError) {
              console.error('[CloseAIAdapter] Failed to parse SSE data:', parseError);
              // 继续处理下一个chunk，不中断流
            }
          }
        }
      }

      console.log(`[CloseAIAdapter] 流式调用完成`, {
        provider: this.provider,
        model: this.modelName,
        chunksReceived: chunkCount,
      });
    } catch (error) {
      console.error(`[CloseAIAdapter] ${this.provider.toUpperCase()} Stream Error:`, error);
      
      if (axios.isAxiosError(error)) {
        const errorMessage = error.response?.data?.error?.message || error.message;
        throw new Error(
          `CloseAI (${this.provider.toUpperCase()}) 流式调用失败: ${errorMessage}`
        );
      }
      
      throw error;
    }
  }
}

