//
//  ProviderRegistry.swift
//  oAI
//
//  Registry for managing multiple AI providers
//
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2026 Rune Olsen
//
// This file is part of oAI.
//
// oAI is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// oAI is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
// Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with oAI. If not, see <https://www.gnu.org/licenses/>.


import Foundation
import os

class ProviderRegistry {
    static let shared = ProviderRegistry()
    
    private var providers: [Settings.Provider: AIProvider] = [:]
    private let settings = SettingsService.shared
    
    private init() {}
    
    // MARK: - Get Provider
    
    func getProvider(for providerType: Settings.Provider) -> AIProvider? {
        // Return cached provider if exists
        if let provider = providers[providerType] {
            return provider
        }
        
        // Create new provider based on type
        let provider: AIProvider?

        switch providerType {
        case .openrouter:
            guard let apiKey = settings.openrouterAPIKey, !apiKey.isEmpty else {
                Log.api.warning("No API key configured for OpenRouter")
                return nil
            }
            provider = OpenRouterProvider(apiKey: apiKey)

        case .anthropic:
            guard let apiKey = settings.anthropicAPIKey, !apiKey.isEmpty else {
                Log.api.warning("No API key configured for Anthropic")
                return nil
            }
            provider = AnthropicProvider(apiKey: apiKey)

        case .openai:
            guard let apiKey = settings.openaiAPIKey, !apiKey.isEmpty else {
                Log.api.warning("No API key configured for OpenAI")
                return nil
            }
            provider = OpenAIProvider(apiKey: apiKey)

        case .ollama:
            provider = OllamaProvider(baseURL: settings.ollamaEffectiveURL)

        case .appleOnDevice:
            provider = AppleFoundationProvider()
        }
        
        // Cache and return
        if let provider = provider {
            Log.api.info("Created \(providerType.rawValue) provider")
            providers[providerType] = provider
        }
        
        return provider
    }
    
    // MARK: - Current Provider
    
    func getCurrentProvider() -> AIProvider? {
        let currentProviderType = settings.defaultProvider
        return getProvider(for: currentProviderType)
    }
    
    // MARK: - Clear Cache
    
    func clearCache() {
        providers.removeAll()
    }
    
    // MARK: - Validate API Key
    
    func hasValidAPIKey(for providerType: Settings.Provider) -> Bool {
        switch providerType {
        case .openrouter:
            return settings.openrouterAPIKey != nil && !settings.openrouterAPIKey!.isEmpty
        case .anthropic:
            return AnthropicOAuthService.shared.isAuthenticated
                || (settings.anthropicAPIKey != nil && !settings.anthropicAPIKey!.isEmpty)
        case .openai:
            return settings.openaiAPIKey != nil && !settings.openaiAPIKey!.isEmpty
        case .ollama:
            return settings.ollamaConfigured
        case .appleOnDevice:
            return true  // no API key needed
        }
    }

    /// Providers that have credentials configured (API key or, for Ollama, a saved URL)
    var configuredProviders: [Settings.Provider] {
        Settings.Provider.allCases.filter { hasValidAPIKey(for: $0) }
    }
}
