import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import {
  LLMProvider,
  ChatMessage,
  ChatOptions,
  ChatResponse,
  StreamCallbacks,
} from '../interfaces/llm-provider.interface';

/**
 * 通义千问 Provider (阿里云百炼)
 * 
 * 支持阿里云百炼 API（OpenAI 兼容模式）
 * 文档: https://help.aliyun.com/zh/model-studio/developer-reference/use-qwen-by-calling-api
 * 
 * 环境变量:
 * - DASHSCOPE_API_KEY: 阿里云百炼 API Key
 * - QWEN_MODEL: 模型名称，默认 qwen-plus
 * - QWEN_BASE_URL: API 地址，默认 https://dashscope.aliyuncs.com/compatible-mode/v1
 */
@Injectable()
export class QwenProvider implements LLMProvider, OnModuleInit {
  private readonly logger = new Logger(QwenProvider.name);
  private client: any = null;
  private readonly defaultModel: string;
  private readonly baseURL: string;
  private isAvailableFlag = false;

  constructor(private readonly configService: ConfigService) {
    // 支持的模型: qwen-turbo, qwen-plus, qwen-max, qwen-max-longcontext, qwen-vl-plus 等
    this.defaultModel = this.configService.get<string>('QWEN_MODEL') || 'qwen-plus';
    this.baseURL = this.configService.get<string>('QWEN_BASE_URL') || 
                   'https://dashscope.aliyuncs.com/compatible-mode/v1';
  }

  async onModuleInit() {
    await this.initializeClient();
  }

  /**
   * 初始化客户端
   * 使用 OpenAI SDK 兼容模式
   */
  private async initializeClient(): Promise<void> {
    try {
      // 使用 require 动态加载 OpenAI SDK
      // eslint-disable-next-line @typescript-eslint/no-var-requires
      const OpenAI = require('openai').default;
      
      const apiKey = this.configService.get<string>('DASHSCOPE_API_KEY');
      
      if (!apiKey) {
        this.logger.warn('DASHSCOPE_API_KEY 未配置，通义千问服务将不可用');
        return;
      }

      // 阿里云百炼兼容 OpenAI 接口
      this.client = new OpenAI({
        apiKey,
        baseURL: this.baseURL,
      });
      
      this.isAvailableFlag = true;
      this.logger.log(`通义千问 Provider 初始化成功 (模型: ${this.defaultModel})`);
    } catch (error: any) {
      if (error.code === 'MODULE_NOT_FOUND') {
        this.logger.warn('OpenAI SDK 未安装，通义千问服务将不可用。请运行: npm install openai');
      } else {
        this.logger.error('通义千问 Provider 初始化失败:', error);
      }
    }
  }

  /**
   * 发送聊天消息并获取完整响应
   */
  async chat(messages: ChatMessage[], options?: ChatOptions): Promise<ChatResponse> {
    if (!this.client) {
      throw new Error('Qwen client not initialized. Please configure DASHSCOPE_API_KEY.');
    }

    const model = options?.model || this.defaultModel;

    try {
      const response = await this.client.chat.completions.create({
        model,
        messages: messages.map((m) => ({
          role: m.role,
          content: m.content,
        })),
        temperature: options?.temperature ?? 0.7,
        max_tokens: options?.maxTokens ?? 2048,
        top_p: options?.topP ?? 0.8,  // 通义千问默认 0.8
        // 通义千问特有参数
        // enable_search: true,  // 启用互联网搜索（可选）
        // result_format: 'message',  // 返回格式
      });

      const choice = response.choices[0];

      return {
        content: choice.message.content || '',
        finishReason: choice.finish_reason as ChatResponse['finishReason'],
        usage: {
          promptTokens: response.usage?.prompt_tokens || 0,
          completionTokens: response.usage?.completion_tokens || 0,
          totalTokens: response.usage?.total_tokens || 0,
        },
      };
    } catch (error: any) {
      this.logger.error('通义千问 chat error:', error?.message || error);
      throw error;
    }
  }

  /**
   * 发送聊天消息并获取流式响应
   */
  async streamChat(
    messages: ChatMessage[],
    callbacks: StreamCallbacks,
    options?: ChatOptions,
  ): Promise<void> {
    if (!this.client) {
      callbacks.onError(new Error('Qwen client not initialized. Please configure DASHSCOPE_API_KEY.'));
      return;
    }

    const model = options?.model || this.defaultModel;
    let fullContent = '';
    let totalUsage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };

    try {
      const stream = await this.client.chat.completions.create({
        model,
        messages: messages.map((m) => ({
          role: m.role,
          content: m.content,
        })),
        temperature: options?.temperature ?? 0.7,
        max_tokens: options?.maxTokens ?? 2048,
        top_p: options?.topP ?? 0.8,
        stream: true,
        // 通义千问流式返回 token 统计
        stream_options: {
          include_usage: true,
        },
      });

      for await (const chunk of stream) {
        const delta = chunk.choices[0]?.delta?.content;
        if (delta) {
          fullContent += delta;
          callbacks.onToken(delta);
        }
        
        // 通义千问在最后一个 chunk 返回 usage
        if (chunk.usage) {
          totalUsage = {
            promptTokens: chunk.usage.prompt_tokens || 0,
            completionTokens: chunk.usage.completion_tokens || 0,
            totalTokens: chunk.usage.total_tokens || 0,
          };
        }
      }

      callbacks.onComplete(fullContent, totalUsage);
    } catch (error: any) {
      this.logger.error('通义千问 stream error:', error?.message || error);
      callbacks.onError(error as Error);
    }
  }

  /**
   * 检查服务是否可用
   */
  async isAvailable(): Promise<boolean> {
    if (!this.client || !this.isAvailableFlag) {
      return false;
    }

    try {
      // 简单的健康检查：发送一个简单请求
      // 注意：阿里云百炼不支持 models.list，使用简单的 chat 测试
      await this.client.chat.completions.create({
        model: this.defaultModel,
        messages: [{ role: 'user', content: 'Hi' }],
        max_tokens: 5,
      });
      return true;
    } catch (error) {
      this.logger.warn('通义千问 service unavailable:', error);
      return false;
    }
  }

  /**
   * 获取当前使用的模型
   */
  getModel(): string {
    return this.defaultModel;
  }

  /**
   * 获取 Provider 名称
   */
  getName(): string {
    return 'qwen';
  }
}
