package llm

import (
	"fmt"
	"log/slog"
	"net/http"
	"time"
)

// Config holds the configuration for an LLM client.
type Config struct {
	// Key is the API key for authentication.
	Key string `yaml:"key"`
	// SystemMessage is prepended to all conversations.
	SystemMessage string `yaml:"system_message"`
	// Timeout is the maximum duration for a query (e.g., "5m").
	// Defaults to 5 minutes if empty.
	Timeout string `yaml:"timeout"`
	// URL is the base URL of the OpenAI-compatible API endpoint.
	URL string `yaml:"url"`
}

// Validate checks that required configuration values are present and valid.
func (cfg Config) Validate() error {
	if cfg.Timeout != "" {
		if _, err := time.ParseDuration(cfg.Timeout); err != nil {
			return fmt.Errorf("invalid timeout: %w", err)
		}
	}
	if cfg.URL == "" {
		return fmt.Errorf("missing URL")
	}
	return nil
}

// Client wraps an OpenAI-compatible client with tool execution support.
type Client struct {
	baseURL       string
	httpc         *http.Client
	key           string
	log           *slog.Logger
	registry      *Registry
	systemMessage string
	timeout       time.Duration
	tools         []APITool
}

// NewClient creates a new LLM client with the provided configuration.
// The registry is optional; if nil, tool calling is disabled.
func NewClient(
	cfg Config,
	registry *Registry,
	log *slog.Logger,
) (*Client, error) {
	if err := cfg.Validate(); err != nil {
		return nil, fmt.Errorf("invalid config: %w", err)
	}

	timeout := 5 * time.Minute
	if cfg.Timeout != "" {
		d, err := time.ParseDuration(cfg.Timeout)
		if err != nil {
			return nil, fmt.Errorf("parse timeout: %v", err)
		}
		timeout = d
	}

	llm := &Client{
		baseURL:       cfg.URL,
		key:           cfg.Key,
		log:           log,
		systemMessage: cfg.SystemMessage,
		registry:      registry,
		httpc:         &http.Client{},
		timeout:       timeout,
	}

	// Convert tools from registry.
	llm.tools = registry.ToAPI()

	return llm, nil
}
