package main

import (
	"encoding/json"
	"fmt"
	"os"
)

// Config holds all login server configuration
type Config struct {
	Port                     int                 `json:"port"`
	MaxConnections           int                 `json:"max_connections"`
	TimeoutSeconds           int                 `json:"timeout_seconds"`
	EnableCompression        bool                `json:"enable_compression"`
	EnableEncryption         bool                `json:"enable_encryption"`
	AllowAccountCreation     bool                `json:"allow_account_creation"`
	DefaultSubscriptionLevel uint32              `json:"default_subscription_level"`
	ExpansionFlag            uint16              `json:"expansion_flag"`
	CitiesFlag               uint8               `json:"cities_flag"`
	EnabledRaces             uint32              `json:"enabled_races"`
	SupportedVersions        []uint16            `json:"supported_versions"`
	Database                 DatabaseConfig      `json:"database"`
	WebServer                WebServerConfig     `json:"web_server"`
	WorldServers             []WorldServerConfig `json:"world_servers"`
}

// WebServerConfig holds web server settings
type WebServerConfig struct {
	Enabled     bool   `json:"enabled"`
	Address     string `json:"address"`
	Port        int    `json:"port"`
	CertFile    string `json:"cert_file"`
	KeyFile     string `json:"key_file"`
	KeyPassword string `json:"key_password"`
	Username    string `json:"username"`
	Password    string `json:"password"`
}

// WorldServerConfig holds world server connection info
type WorldServerConfig struct {
	ID          int32  `json:"id"`
	Name        string `json:"name"`
	Address     string `json:"address"`
	Port        int    `json:"port"`
	SharedKey   string `json:"shared_key"`
	AutoConnect bool   `json:"auto_connect"`
}

// DefaultConfig returns sensible default configuration
func DefaultConfig() *Config {
	return &Config{
		Port:                     5999,
		MaxConnections:           1000,
		TimeoutSeconds:           45,
		EnableCompression:        true,
		EnableEncryption:         true,
		AllowAccountCreation:     false,
		DefaultSubscriptionLevel: 0xFFFFFFFF,
		ExpansionFlag:            0x7CFF,
		CitiesFlag:               0xFF,
		EnabledRaces:             0xFFFF,
		SupportedVersions:        []uint16{283, 373, 546, 561, 1096, 1208},
		Database: DatabaseConfig{
			FilePath:       "eq2login.db",
			MaxConnections: 10,
			BusyTimeout:    5000,
		},
		WebServer: WebServerConfig{
			Enabled: true,
			Address: "0.0.0.0",
			Port:    8080,
		},
	}
}

// LoadConfig loads configuration from a JSON file
func LoadConfig(filename string) (*Config, error) {
	// Start with defaults
	config := DefaultConfig()

	// Check if config file exists
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		// Create default config file
		if err := SaveConfig(filename, config); err != nil {
			return nil, fmt.Errorf("failed to create default config: %w", err)
		}
		fmt.Printf("Created default configuration file: %s\n", filename)
		return config, nil
	}

	// Read existing config file
	data, err := os.ReadFile(filename)
	if err != nil {
		return nil, fmt.Errorf("failed to read config file: %w", err)
	}

	// Parse JSON
	if err := json.Unmarshal(data, config); err != nil {
		return nil, fmt.Errorf("failed to parse config JSON: %w", err)
	}

	// Validate configuration
	if err := config.Validate(); err != nil {
		return nil, fmt.Errorf("invalid configuration: %w", err)
	}

	return config, nil
}

// SaveConfig saves configuration to a JSON file
func SaveConfig(filename string, config *Config) error {
	data, err := json.MarshalIndent(config, "", "	")
	if err != nil {
		return fmt.Errorf("failed to marshal config: %w", err)
	}

	if err := os.WriteFile(filename, data, 0644); err != nil {
		return fmt.Errorf("failed to write config file: %w", err)
	}

	return nil
}

// Validate checks if the configuration is valid
func (c *Config) Validate() error {
	if c.Port < 1 || c.Port > 65535 {
		return fmt.Errorf("invalid port: %d", c.Port)
	}

	if c.MaxConnections < 1 {
		return fmt.Errorf("max_connections must be positive")
	}

	if c.TimeoutSeconds < 1 {
		return fmt.Errorf("timeout_seconds must be positive")
	}

	if len(c.SupportedVersions) == 0 {
		return fmt.Errorf("must specify at least one supported version")
	}

	return nil
}

// IsVersionSupported checks if a client version is supported
func (c *Config) IsVersionSupported(version uint16) bool {
	for _, supported := range c.SupportedVersions {
		if supported == version {
			return true
		}
	}
	return false
}

// GetWorldServerConfig returns configuration for a specific world server
func (c *Config) GetWorldServerConfig(id int32) *WorldServerConfig {
	for i := range c.WorldServers {
		if c.WorldServers[i].ID == id {
			return &c.WorldServers[i]
		}
	}
	return nil
}
