package llm

import (
	"context"
	"fmt"
	"log/slog"

	"github.com/enmanuel/agents/internal/config"
	coretypes "github.com/enmanuel/agents/pkg/llm"
)

// FromConfig builds a CompleteFunc from an LLMProviderCfg.
func FromConfig(cfg config.LLMProviderCfg, log *slog.Logger) (coretypes.CompleteFunc, error) {
	log.Info("llm_provider_init", "provider", cfg.Provider, "model", cfg.Model)
	switch cfg.Provider {
	case "anthropic":
		return NewAnthropicComplete(cfg.APIKeyEnv, cfg.BaseURL, log), nil
	case "openai":
		return NewOpenAIComplete(cfg.APIKeyEnv, cfg.BaseURL, log), nil
	case "ollama":
		base := cfg.BaseURL
		if base == "" {
			base = "http://localhost:11434/v1"
		}
		return NewOpenAIComplete("OLLAMA_API_KEY", base, log), nil
	case "claude-code":
		return NewClaudeCodeComplete(cfg.ClaudeCode, log), nil
	default:
		return nil, fmt.Errorf("unknown LLM provider: %s", cfg.Provider)
	}
}

// WithFallback wraps primary with a fallback CompleteFunc.
// If primary returns an error, fallback is tried with the fallback config's model.
func WithFallback(primary, fallback coretypes.CompleteFunc, fallbackCfg config.LLMProviderCfg, log *slog.Logger) coretypes.CompleteFunc {
	return func(ctx context.Context, req coretypes.CompletionRequest) (coretypes.CompletionResponse, error) {
		resp, err := primary(ctx, req)
		if err != nil {
			log.Warn("llm_fallback_triggered", "primary_err", err)
			// Override request fields with fallback config values
			if fallbackCfg.Model != "" {
				req.Model = fallbackCfg.Model
			}
			if fallbackCfg.MaxTokens > 0 {
				req.MaxTokens = fallbackCfg.MaxTokens
			}
			return fallback(ctx, req)
		}
		return resp, nil
	}
}
