package config

import (
	"fmt"
	"os"
	"path/filepath"

	"gopkg.in/yaml.v3"
)

type Config struct {
	Port              int      `yaml:"port"`
	CursorCLIPath     string   `yaml:"cursor_cli_path"`
	DefaultModel      string   `yaml:"default_model"`
	Timeout           int      `yaml:"timeout"`
	MaxConcurrent     int      `yaml:"max_concurrent"`
	UseACP            bool     `yaml:"use_acp"`
	ChatOnlyWorkspace bool     `yaml:"chat_only_workspace"`
	LogLevel          string   `yaml:"log_level"`
	AvailableModels   []string `yaml:"available_models,omitempty"`
}

// Defaults returns a Config populated with default values.
//
// ChatOnlyWorkspace defaults to true. This is the cursor-api-proxy posture:
// every Cursor CLI / ACP child is spawned in an empty temp directory with
// HOME / CURSOR_CONFIG_DIR overridden so it cannot see the host user's real
// project files or global ~/.cursor rules. Set to false only if you really
// want the Cursor agent to have access to the cwd where cursor-adapter
// started.
func Defaults() Config {
	return Config{
		Port:              8976,
		CursorCLIPath:     "agent",
		DefaultModel:      "auto",
		Timeout:           300,
		MaxConcurrent:     5,
		UseACP:            false,
		ChatOnlyWorkspace: true,
		LogLevel:          "INFO",
	}
}

// Load reads a YAML config file from path. If path is empty it defaults to
// ~/.cursor-adapter/config.yaml. When the file does not exist, a config with
// default values is returned without an error.
func Load(path string) (*Config, error) {
	if path == "" {
		home, err := os.UserHomeDir()
		if err != nil {
			return nil, fmt.Errorf("resolving home directory: %w", err)
		}
		path = filepath.Join(home, ".cursor-adapter", "config.yaml")
	}

	data, err := os.ReadFile(path)
	if err != nil {
		if os.IsNotExist(err) {
			c := Defaults()
			return &c, nil
		}
		return nil, fmt.Errorf("reading config file %s: %w", path, err)
	}

	cfg := Defaults()
	if err := yaml.Unmarshal(data, &cfg); err != nil {
		return nil, fmt.Errorf("parsing config file %s: %w", path, err)
	}

	if err := cfg.validate(); err != nil {
		return nil, fmt.Errorf("validating config: %w", err)
	}

	return &cfg, nil
}

func (c *Config) validate() error {
	if c.Port <= 0 {
		return fmt.Errorf("port must be > 0, got %d", c.Port)
	}
	if c.CursorCLIPath == "" {
		return fmt.Errorf("cursor_cli_path must not be empty")
	}
	if c.Timeout <= 0 {
		return fmt.Errorf("timeout must be > 0, got %d", c.Timeout)
	}
	return nil
}
