import { $ } from "bun";
import type { Config } from "./schema";
import { defaultConfig } from "./schema";

export class ConfigManager {
  private static configPath = `${process.env.HOME}/.agi/config.json`;
  private static config: Config | null = null;

  static async load(): Promise<Config> {
    if (this.config) return this.config;

    try {
      const file = Bun.file(this.configPath);
      const exists = await file.exists();
      
      if (!exists) {
        await this.init();
        return this.config!;
      }

      this.config = await file.json();
      return this.config!;
    } catch (error) {
      console.warn("Failed to load config, using defaults");
      this.config = defaultConfig;
      return this.config;
    }
  }

  static async init(): Promise<void> {
    const configDir = `${process.env.HOME}/.agi`;
    await $`mkdir -p ${configDir}`.quiet();
    
    this.config = defaultConfig;
    await this.save();
  }

  static async save(): Promise<void> {
    if (!this.config) return;
    
    // Ensure config directory exists
    const configDir = `${process.env.HOME}/.agi`;
    await $`mkdir -p ${configDir}`.quiet();
    
    const file = Bun.file(this.configPath);
    await Bun.write(file, JSON.stringify(this.config, null, 2));
  }

  static async get<K extends keyof Config>(key: K): Promise<Config[K]> {
    const config = await this.load();
    return config[key];
  }

  static async set<K extends keyof Config>(key: K, value: Config[K]): Promise<void> {
    const config = await this.load();
    config[key] = value;
    this.config = config; // Update cached config
    await this.save();
  }

  static async getApiKey(provider: string): Promise<string | undefined> {
    const config = await this.load();
    const providerConfig = config.providers[provider as keyof typeof config.providers];
    
    if (!providerConfig || !("apiKey" in providerConfig)) {
      // Fallback to environment variable
      const envVarName = `${provider.toUpperCase()}_API_KEY`;
      return process.env[envVarName];
    }

    const apiKey = providerConfig.apiKey;
    
    // If apiKey is set in config, use it
    if (apiKey && !apiKey.startsWith("env:")) {
      return apiKey;
    }
    
    // If apiKey starts with "env:", get from environment
    if (apiKey?.startsWith("env:")) {
      const envVar = apiKey.substring(4);
      return process.env[envVar];
    }
    
    // Final fallback to standard environment variable
    const envVarName = `${provider.toUpperCase()}_API_KEY`;
    return process.env[envVarName];
  }

  static async setApiKey(provider: string, apiKey: string): Promise<void> {
    const config = await this.load();
    const providerConfig = config.providers[provider as keyof typeof config.providers];
    
    if (providerConfig) {
      (providerConfig as any).apiKey = apiKey;
      this.config = config; // Update cached config
      await this.save();
    } else {
      throw new Error(`Provider ${provider} is not configured`);
    }
  }
}