package agent

import (
	anthropicmessages "github.com/memohai/twilight-ai/provider/anthropic/messages"
	googlegenerative "github.com/memohai/twilight-ai/provider/google/generativeai"
	openaicompletions "github.com/memohai/twilight-ai/provider/openai/completions"
	openairesponses "github.com/memohai/twilight-ai/provider/openai/responses"
	sdk "github.com/memohai/twilight-ai/sdk"
)

// ClientType constants matching the database model configuration.
const (
	ClientTypeOpenAICompletions  = "openai-completions"
	ClientTypeOpenAIResponses    = "openai-responses"
	ClientTypeAnthropicMessages  = "anthropic-messages"
	ClientTypeGoogleGenerativeAI = "google-generative-ai"
)

// Reasoning budget maps per client type.
var (
	anthropicBudget = map[string]int{"low": 5000, "medium": 16000, "high": 50000}
	googleBudget    = map[string]int{"low": 5000, "medium": 16000, "high": 50000}
)

// CreateModel builds a Twilight AI SDK Model from the resolved model config.
func CreateModel(cfg ModelConfig) *sdk.Model {
	switch cfg.ClientType {
	case ClientTypeOpenAICompletions:
		opts := []openaicompletions.Option{
			openaicompletions.WithAPIKey(cfg.APIKey),
		}
		if cfg.BaseURL != "" {
			opts = append(opts, openaicompletions.WithBaseURL(cfg.BaseURL))
		}
		p := openaicompletions.New(opts...)
		return p.ChatModel(cfg.ModelID)

	case ClientTypeOpenAIResponses:
		opts := []openairesponses.Option{
			openairesponses.WithAPIKey(cfg.APIKey),
		}
		if cfg.BaseURL != "" {
			opts = append(opts, openairesponses.WithBaseURL(cfg.BaseURL))
		}
		p := openairesponses.New(opts...)
		return p.ChatModel(cfg.ModelID)

	case ClientTypeAnthropicMessages:
		opts := []anthropicmessages.Option{
			anthropicmessages.WithAPIKey(cfg.APIKey),
		}
		if cfg.BaseURL != "" {
			opts = append(opts, anthropicmessages.WithBaseURL(cfg.BaseURL))
		}
		if cfg.ReasoningConfig != nil && cfg.ReasoningConfig.Enabled {
			budget := ReasoningBudgetTokens(ClientTypeAnthropicMessages, cfg.ReasoningConfig.Effort)
			opts = append(opts, anthropicmessages.WithThinking(anthropicmessages.ThinkingConfig{
				Type:         "enabled",
				BudgetTokens: budget,
			}))
		}
		p := anthropicmessages.New(opts...)
		return p.ChatModel(cfg.ModelID)

	case ClientTypeGoogleGenerativeAI:
		opts := []googlegenerative.Option{
			googlegenerative.WithAPIKey(cfg.APIKey),
		}
		if cfg.BaseURL != "" {
			opts = append(opts, googlegenerative.WithBaseURL(cfg.BaseURL))
		}
		p := googlegenerative.New(opts...)
		return p.ChatModel(cfg.ModelID)

	default:
		// OpenAI-compatible fallback
		opts := []openaicompletions.Option{
			openaicompletions.WithAPIKey(cfg.APIKey),
		}
		if cfg.BaseURL != "" {
			opts = append(opts, openaicompletions.WithBaseURL(cfg.BaseURL))
		}
		p := openaicompletions.New(opts...)
		return p.ChatModel(cfg.ModelID)
	}
}

// BuildReasoningOptions returns SDK generation options for reasoning/thinking.
func BuildReasoningOptions(cfg ModelConfig) []sdk.GenerateOption {
	if cfg.ReasoningConfig == nil || !cfg.ReasoningConfig.Enabled {
		return nil
	}
	effort := cfg.ReasoningConfig.Effort
	if effort == "" {
		effort = "medium"
	}

	switch cfg.ClientType {
	case ClientTypeAnthropicMessages:
		// Anthropic uses thinking budget — no SDK option, handled by provider
		return nil
	case ClientTypeOpenAIResponses, ClientTypeOpenAICompletions:
		return []sdk.GenerateOption{sdk.WithReasoningEffort(effort)}
	case ClientTypeGoogleGenerativeAI:
		return nil
	default:
		return []sdk.GenerateOption{sdk.WithReasoningEffort(effort)}
	}
}

// ReasoningBudgetTokens returns the token budget for extended thinking based on client type and effort.
func ReasoningBudgetTokens(clientType, effort string) int {
	if effort == "" {
		effort = "medium"
	}
	switch clientType {
	case ClientTypeAnthropicMessages:
		if b, ok := anthropicBudget[effort]; ok {
			return b
		}
		return anthropicBudget["medium"]
	case ClientTypeGoogleGenerativeAI:
		if b, ok := googleBudget[effort]; ok {
			return b
		}
		return googleBudget["medium"]
	default:
		return 0
	}
}
