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

export class QwenAdapter implements ILLMAdapter {
  modelName: string;
  private apiKey: string;
  private baseURL: string;

  constructor(modelName: string = 'qwen-turbo') {
    this.modelName = modelName;
    this.apiKey = config.dashscopeApiKey || '';
    this.baseURL = 'https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation';

    if (!this.apiKey) {
      throw new Error('DashScope API key is not configured. Please set DASHSCOPE_API_KEY in .env file.');
    }
  }

  // 非流式调用
  async chat(messages: Message[], options?: LLMOptions): Promise<LLMResponse> {
    try {
      const response = await axios.post(
        this.baseURL,
        {
          model: this.modelName,
          input: {
            messages: messages,
          },
          parameters: {
            temperature: options?.temperature ?? 0.7,
            max_tokens: options?.maxTokens ?? 2000,
            top_p: options?.topP ?? 0.9,
            result_format: 'message',
          },
        },
        {
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${this.apiKey}`,
          },
          timeout: 180000, // 180秒超时（3分钟）- 稿件评估需要更长时间
        }
      );

      const output = response.data.output;
      const usage = response.data.usage;

      return {
        content: output.choices[0].message.content,
        model: this.modelName,
        usage: {
          promptTokens: usage.input_tokens,
          completionTokens: usage.output_tokens,
          totalTokens: usage.total_tokens || usage.input_tokens + usage.output_tokens,
        },
        finishReason: output.choices[0].finish_reason,
      };
    } catch (error: unknown) {
      console.error('Qwen API Error:', error);
      if (axios.isAxiosError(error)) {
        throw new Error(
          `Qwen API调用失败: ${error.response?.data?.message || error.message}`
        );
      }
      throw error;
    }
  }

  // 流式调用
  async *chatStream(
    messages: Message[],
    options?: LLMOptions,
    onChunk?: (chunk: StreamChunk) => void
  ): AsyncGenerator<StreamChunk, void, unknown> {
    try {
      // Qwen-Long需要更长的超时时间（全文模式可能传输~750K tokens）
      const timeout = this.modelName === 'qwen-long' ? 300000 : 60000; // 5分钟 vs 1分钟
      
      console.log(`[QwenAdapter] 开始流式调用`, {
        model: this.modelName,
        timeout: `${timeout / 1000}秒`,
        messagesCount: messages.length,
      });

      const response = await axios.post(
        this.baseURL,
        {
          model: this.modelName,
          input: {
            messages: messages,
          },
          parameters: {
            temperature: options?.temperature ?? 0.7,
            max_tokens: options?.maxTokens ?? 2000,
            top_p: options?.topP ?? 0.9,
            result_format: 'message',
            incremental_output: true,
          },
        },
        {
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${this.apiKey}`,
            'X-DashScope-SSE': 'enable',
          },
          responseType: 'stream',
          timeout: timeout,
        }
      );

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

      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.startsWith(':')) {
            continue;
          }

          if (trimmedLine.startsWith('data:')) {
            try {
              const jsonStr = trimmedLine.slice(5).trim();
              const data = JSON.parse(jsonStr);
              
              const output = data.output;
              const choice = output.choices[0];
              const content = choice.message?.content || '';
              
              const streamChunk: StreamChunk = {
                content: content,
                done: choice.finish_reason === 'stop',
                model: this.modelName,
              };

              if (choice.finish_reason === 'stop' && data.usage) {
                streamChunk.usage = {
                  promptTokens: data.usage.input_tokens,
                  completionTokens: data.usage.output_tokens,
                  totalTokens: data.usage.total_tokens || data.usage.input_tokens + data.usage.output_tokens,
                };
              }

              if (onChunk) {
                onChunk(streamChunk);
              }

              yield streamChunk;
            } catch (parseError) {
              console.error('Failed to parse Qwen SSE data:', parseError);
            }
          }
        }
      }
    } catch (error) {
      console.error('Qwen Stream Error:', error);
      if (axios.isAxiosError(error)) {
        throw new Error(
          `Qwen流式调用失败: ${error.response?.data?.message || error.message}`
        );
      }
      throw error;
    }
  }
}

