import { GoogleGenAI } from "@google/genai";
import type { AIProvider, GenerateOptions } from "./base";
import { ConfigManager } from "../config/manager";

export class GeminiProvider implements AIProvider {
  name = "gemini";
  private client: GoogleGenAI | null = null;

  private async getClient(): Promise<GoogleGenAI> {
    if (this.client) return this.client;

    const apiKey =
      (await ConfigManager.getApiKey("gemini")) || process.env.GEMINI_API_KEY;

    if (!apiKey) {
      console.error("\n❌ Gemini API key not found");
      console.error("\nTo set your API key, use one of these methods:");
      console.error(
        "1. Set environment variable: export GEMINI_API_KEY='your-key'",
      );
      console.error("2. Add to config: agi config key gemini 'your-key'");
      console.error(
        "\nGet your API key from: https://aistudio.google.com/app/apikey",
      );
      process.exit(1);
    }

    // Create client with API key
    this.client = new GoogleGenAI({
      apiKey: apiKey,
    });
    return this.client;
  }

  private async getModelName(): Promise<string> {
    const config = await ConfigManager.get("providers");
    return config.gemini?.model || "gemini-2.0-flash-exp";
  }
  
  supportsStructuredOutput(): boolean {
    return true;
  }

  async validateConfig(): Promise<boolean> {
    try {
      const client = await this.getClient();
      const model = await this.getModelName();
      await client.models.generateContent({
        model,
        contents: "test",
      });
      return true;
    } catch {
      return false;
    }
  }

  async generateContent(
    prompt: string,
    options?: GenerateOptions,
  ): Promise<string> {
    const client = await this.getClient();
    const defaultModel = await this.getModelName();

    const model = options?.model || defaultModel;

    const response = await client.models.generateContent({
      model,
      contents: prompt,
    });

    return response.text || "";
  }
  
  async generateStructuredContent(
    prompt: string,
    schema: any,
    options?: GenerateOptions
  ): Promise<string> {
    const client = await this.getClient();
    const defaultModel = await this.getModelName();
    const model = options?.model || defaultModel;
    
    // Use Gemini's structured output capabilities
    const response = await client.models.generateContent({
      model,
      contents: prompt,
      config: {
        responseMimeType: "application/json",
        responseSchema: schema,
      },
    });
    
    return response.text || "";
  }
}
