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

/**
 * OpenAI Provider
 * 
 * 支持 OpenAI API 和 Azure OpenAI API
 * 
 * 注意：需要安装 openai 包：npm install openai
 */
@Injectable()
export class OpenAIProvider implements LLMProvider, OnModuleInit {
  private readonly logger = new Logger(OpenAIProvider.name);
  private client: any = null;
  private readonly defaultModel: string;
  private isAvailableFlag = false;

  constructor(private readonly configService: ConfigService) {
    this.defaultModel = this.configService.get<string>('OPENAI_MODEL') || 'gpt-4-turbo';
  }

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

  /**
   * 初始化 OpenAI 客户端
   */
  private async initializeClient(): Promise<void> {
    try {
      // 使用 require 动态加载，避免类型检查问题
      // eslint-disable-next-line @typescript-eslint/no-var-requires
      const OpenAI = require('openai').default;
      
      const apiKey = this.configService.get<string>('OPENAI_API_KEY');
      const baseURL = this.configService.get<string>('OPENAI_BASE_URL');
      
      if (!apiKey) {
        this.logger.warn('OPENAI_API_KEY 未配置，LLM 服务将不可用');
        return;
      }

      this.client = new OpenAI({
        apiKey,
        baseURL: baseURL || undefined,
      });
      
      this.isAvailableFlag = true;
      this.logger.log('OpenAI Provider 初始化成功');
    } catch (error: any) {
      if (error.code === 'MODULE_NOT_FOUND') {
        this.logger.warn('OpenAI SDK 未安装，LLM 服务将不可用。请运行: npm install openai');
      } else {
        this.logger.error('OpenAI Provider 初始化失败:', error);
      }
    }
  }

  /**
   * 发送聊天消息并获取完整响应
   */
  async chat(messages: ChatMessage[], options?: ChatOptions): Promise<ChatResponse> {
    if (!this.client) {
      throw new Error('OpenAI client not initialized. Please install openai package and configure OPENAI_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 ?? 1,
        frequency_penalty: options?.frequencyPenalty ?? 0,
        presence_penalty: options?.presencePenalty ?? 0,
        stop: options?.stop,
      });

      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) {
      this.logger.error('OpenAI chat error:', error);
      throw error;
    }
  }

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

    const model = options?.model || this.defaultModel;
    let fullContent = '';

    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,
        stream: true,
      });

      for await (const chunk of stream) {
        const delta = chunk.choices[0]?.delta?.content;
        if (delta) {
          fullContent += delta;
          callbacks.onToken(delta);
        }
      }

      callbacks.onComplete(fullContent);
    } catch (error) {
      this.logger.error('OpenAI stream error:', error);
      callbacks.onError(error as Error);
    }
  }

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

    try {
      // 简单的健康检查：获取模型列表
      await this.client.models.list();
      return true;
    } catch (error) {
      this.logger.warn('OpenAI service unavailable:', error);
      return false;
    }
  }
}
