package config

import (
	"fmt"

	"github.com/spf13/viper"
)

// Config holds all Tongo Core configuration values.
type Config struct {
	Daemon  DaemonConfig  `mapstructure:"daemon"`
	Valkey  ValkeyConfig  `mapstructure:"valkey"`
	Engine  EngineConfig  `mapstructure:"engine"`
	Combat  CombatConfig  `mapstructure:"combat"`
	Markets MarketsConfig `mapstructure:"markets"`
}

// DaemonConfig holds parameters for the daemon runtime.
type DaemonConfig struct {
	TickIntervalMs int    `mapstructure:"tick_interval_ms"`
	LogLevel       string `mapstructure:"log_level"`
}

// ValkeyConfig holds connections settings for Valkey/Redis.
type ValkeyConfig struct {
	Host     string `mapstructure:"host"`
	Port     int    `mapstructure:"port"`
	Password string `mapstructure:"password"`
	DB       int    `mapstructure:"db"`
}

// EngineConfig holds high-level simulation settings.
type EngineConfig struct {
	TargetActiveMatches    int    `mapstructure:"target_active_matches"`
	MaxActiveMatches       int    `mapstructure:"max_active_matches"`
	MinActiveMatches       int    `mapstructure:"min_active_matches"`
	PreMatchDurationTicks  int    `mapstructure:"pre_match_duration_ticks"`
	MinMatchDurationTicks  int    `mapstructure:"min_match_duration_ticks"`
	MaxMatchDurationTicks  int    `mapstructure:"max_match_duration_ticks"`
	ResolvingDurationTicks int    `mapstructure:"resolving_duration_ticks"`
	TaxonomyPath           string `mapstructure:"taxonomy_path"`
}

// CombatConfig holds modifiers for combat simulation.
type CombatConfig struct {
	DamageScalingFactor   float64 `mapstructure:"damage_scaling_factor"`
	DamageVarianceLow     float64 `mapstructure:"damage_variance_low"`
	DamageVarianceHigh    float64 `mapstructure:"damage_variance_high"`
	CriticalHitChance     float64 `mapstructure:"critical_hit_chance"`
	CriticalHitMultiplier float64 `mapstructure:"critical_hit_multiplier"`
}

// MarketsConfig holds parameters for overround margin and price limits.
type MarketsConfig struct {
	PrimaryMargin   float64 `mapstructure:"primary_margin"`
	SecondaryMargin float64 `mapstructure:"secondary_margin"`
	ExoticMargin    float64 `mapstructure:"exotic_margin"`
	MinPrice        float64 `mapstructure:"min_price"`
	MaxPrice        float64 `mapstructure:"max_price"`
	MinProbability  float64 `mapstructure:"min_probability"`
	MaxProbability  float64 `mapstructure:"max_probability"`
}

// Load reads configuration from the config file and environment variables.
func Load() (*Config, error) {
	viper.SetConfigName("tongo")
	viper.SetConfigType("yaml")
	viper.AddConfigPath("./config")
	viper.AddConfigPath(".")
	viper.SetEnvPrefix("TONGO")
	viper.AutomaticEnv()

	// Defaults
	viper.SetDefault("daemon.tick_interval_ms", 2000)
	viper.SetDefault("daemon.log_level", "info")

	viper.SetDefault("valkey.host", "localhost")
	viper.SetDefault("valkey.port", 6379)
	viper.SetDefault("valkey.password", "")
	viper.SetDefault("valkey.db", 0)

	viper.SetDefault("engine.target_active_matches", 8)
	viper.SetDefault("engine.max_active_matches", 12)
	viper.SetDefault("engine.min_active_matches", 4)
	viper.SetDefault("engine.pre_match_duration_ticks", 30)
	viper.SetDefault("engine.min_match_duration_ticks", 60)
	viper.SetDefault("engine.max_match_duration_ticks", 150)
	viper.SetDefault("engine.resolving_duration_ticks", 3)
	viper.SetDefault("engine.taxonomy_path", "../data-source/taxonomy.yaml")

	viper.SetDefault("combat.damage_scaling_factor", 0.1)
	viper.SetDefault("combat.damage_variance_low", 0.6)
	viper.SetDefault("combat.damage_variance_high", 1.4)
	viper.SetDefault("combat.critical_hit_chance", 0.05)
	viper.SetDefault("combat.critical_hit_multiplier", 3.0)

	viper.SetDefault("markets.primary_margin", 1.06)
	viper.SetDefault("markets.secondary_margin", 1.075)
	viper.SetDefault("markets.exotic_margin", 1.12)
	viper.SetDefault("markets.min_price", 1.01)
	viper.SetDefault("markets.max_price", 51.00)
	viper.SetDefault("markets.min_probability", 0.02)
	viper.SetDefault("markets.max_probability", 0.98)

	if err := viper.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
			return nil, fmt.Errorf("reading config: %w", err)
		}
	}

	var cfg Config
	if err := viper.Unmarshal(&cfg); err != nil {
		return nil, fmt.Errorf("unmarshaling config: %w", err)
	}

	return &cfg, nil
}
