import { Injectable, Logger } from "@nestjs/common"
import axios from "axios"
import https from "https"

interface AiCallOptions {
  systemPrompt: string
  userMessage: string
  temperature?: number
  maxTokens?: number
}

const httpAgent = new https.Agent({ rejectUnauthorized: true, keepAlive: true })

@Injectable()
export class AiService {
  private readonly logger = new Logger(AiService.name)

  private readonly primaryUrl = process.env.AI_PRIMARY_URL || "https://token.sensenova.cn/v1"
  private readonly primaryKey = process.env.AI_PRIMARY_KEY || ""
  private readonly primaryModel = process.env.AI_PRIMARY_MODEL || "deepseek-v4-flash"
  private readonly primaryFallbackModel = process.env.AI_PRIMARY_FALLBACK_MODEL || "sensenova-6.7-flash-lite"

  private readonly backupUrl = process.env.AI_BACKUP_URL || "https://integrate.api.nvidia.com/v1"
  private readonly backupKey = process.env.AI_BACKUP_KEY || ""
  private readonly backupModel = process.env.AI_BACKUP_MODEL || "meta/llama-3.1-8b-instruct"

  async call(options: AiCallOptions): Promise<string> {
    const { systemPrompt, userMessage, temperature = 0.7, maxTokens = 2048 } = options

    // Try primary AI (deepseek-v4-flash on sensenova)
    try {
      const result = await this.callApi(this.primaryUrl, this.primaryKey, this.primaryModel, systemPrompt, userMessage, temperature, maxTokens, 60000)
      if (result) return result
      // Primary returned empty content (thinking model exhausted tokens); retry with more tokens
      const retry = await this.callApi(this.primaryUrl, this.primaryKey, this.primaryModel, systemPrompt, userMessage, temperature, Math.min(maxTokens * 2, 4096), 60000)
      if (retry) return retry
    } catch (e) {
      this.logger.warn(`Primary AI failed: ${(e as Error).message}, trying primary fallback...`)
    }

    // Try primary fallback model (sensenova-6.7-flash-lite, same provider)
    try {
      const result = await this.callApi(this.primaryUrl, this.primaryKey, this.primaryFallbackModel, systemPrompt, userMessage, temperature, maxTokens, 60000)
      if (result) return result
    } catch (e) {
      this.logger.warn(`Primary fallback AI also failed: ${(e as Error).message}, trying backup...`)
    }

    // Try backup AI (NVIDIA - meta/llama-3.1-8b-instruct)
    try {
      const result = await this.callApi(this.backupUrl, this.backupKey, this.backupModel, systemPrompt, userMessage, temperature, Math.max(maxTokens, 2048), 120000)
      if (result) return result
    } catch (e) {
      this.logger.warn(`Backup AI also failed: ${(e as Error).message}`)
    }

    throw new Error("AI 服务暂时不可用，请稍后重试")
  }

  private async callApi(
    baseUrl: string, apiKey: string, model: string,
    systemPrompt: string, userMessage: string,
    temperature: number, maxTokens: number, timeout: number,
  ): Promise<string | null> {
    try {
      const res = await axios.post(
        `${baseUrl}/chat/completions`,
        {
          model,
          messages: [
            { role: "system", content: systemPrompt },
            { role: "user", content: userMessage },
          ],
          temperature,
          max_tokens: maxTokens,
        },
        {
          headers: {
            "Authorization": `Bearer ${apiKey}`,
            "Content-Type": "application/json",
          },
          timeout,
          httpsAgent: httpAgent,
          transitional: { clarifyTimeoutError: true },
        },
      )
      return res.data?.choices?.[0]?.message?.content || null
    } catch (e: any) {
      if (e.code === 'ECONNABORTED') {
        this.logger.warn(`AI call timeout (${timeout}ms): ${model}`)
      }
      return null
    }
  }
}
