import { Injectable, Logger } from "@nestjs/common"
import { GoogleGenAI } from "@google/genai"

@Injectable()
export class GeminiService {
  private readonly logger = new Logger(GeminiService.name)
  private ai = new GoogleGenAI({
    apiKey: process.env.GEMINI_API_KEY!,
  })

  // Rate limiting: Free tier allows 5 requests per minute
  private readonly MAX_REQUESTS_PER_MINUTE = 5
  private readonly RATE_LIMIT_WINDOW = 60 * 1000 // 1 minute in milliseconds
  private requestTimestamps: number[] = []

  async generateText(prompt: string): Promise<string> {
    return this.generateTextWithRetry(prompt, 3)
  }

  private async generateTextWithRetry(
    prompt: string,
    maxRetries: number,
  ): Promise<string> {
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
      try {
        // Wait for rate limit if needed
        await this.waitForRateLimit()

        // Record this request timestamp
        this.recordRequest()

        const response = await this.ai.models.generateContent({
          model: "gemini-3.1-flash-lite-preview",
          contents: prompt,
        })

        this.logger.log(`Gemini API call successful on attempt ${attempt}`)
        return response.text
      } catch (error) {
        const isRateLimitError =
          error.message?.includes("429") ||
          error.message?.includes("quota") ||
          error.message?.includes("RESOURCE_EXHAUSTED")

        if (isRateLimitError && attempt < maxRetries) {
          // Extract retry delay from error message if available
          const retryDelayMatch = error.message?.match(
            /retry in (\d+(?:\.\d+)?)s/,
          )
          const retryDelay = retryDelayMatch
            ? parseFloat(retryDelayMatch[1]) * 1000
            : 60000 // Default 60s

          this.logger.warn(
            `Rate limit exceeded on attempt ${attempt}/${maxRetries}. Retrying in ${retryDelay / 1000}s...`,
          )

          await this.sleep(retryDelay)
          continue
        }

        this.logger.error(
          `Gemini API error on attempt ${attempt}/${maxRetries}: ${error.message}`,
        )

        if (attempt === maxRetries) {
          // Mark this as a critical API failure that should stop the entire process
          throw new Error(
            `CRITICAL_API_FAILURE: Gemini API failed after ${maxRetries} attempts: ${error.message}`,
          )
        }
      }
    }

    throw new Error("Unexpected error in generateTextWithRetry")
  }

  private async waitForRateLimit(): Promise<void> {
    const now = Date.now()

    // Remove timestamps older than the rate limit window
    this.requestTimestamps = this.requestTimestamps.filter(
      (timestamp) => now - timestamp < this.RATE_LIMIT_WINDOW,
    )

    // If we're at the limit, wait until the oldest request expires
    if (this.requestTimestamps.length >= this.MAX_REQUESTS_PER_MINUTE) {
      const oldestRequest = Math.min(...this.requestTimestamps)
      const waitTime = this.RATE_LIMIT_WINDOW - (now - oldestRequest) + 1000 // Add 1s buffer

      if (waitTime > 0) {
        this.logger.log(
          `Rate limit reached. Waiting ${waitTime / 1000}s before next request...`,
        )
        await this.sleep(waitTime)
      }
    }
  }

  private recordRequest(): void {
    this.requestTimestamps.push(Date.now())
  }

  private sleep(ms: number): Promise<void> {
    return new Promise((resolve) => setTimeout(resolve, ms))
  }
}
