package main

import (
	"fmt"
	"strings"
)

// ValidateConfig performs comprehensive validation of the server configuration
func (c *Config) Validate() error {
	// Validate server settings
	if c.Server.Name == "" {
		return fmt.Errorf("server name cannot be empty")
	}

	if c.Server.Network == "" {
		return fmt.Errorf("network name cannot be empty")
	}

	if c.Server.Listen.Host == "" {
		c.Server.Listen.Host = "localhost" // Default fallback
	}

	if c.Server.Listen.Port <= 0 || c.Server.Listen.Port > 65535 {
		return fmt.Errorf("invalid port number: %d", c.Server.Listen.Port)
	}

	if c.Server.Listen.EnableSSL && (c.Server.Listen.SSLPort <= 0 || c.Server.Listen.SSLPort > 65535) {
		return fmt.Errorf("invalid SSL port number: %d", c.Server.Listen.SSLPort)
	}

	// Validate limits
	if c.Limits.MaxClients <= 0 {
		c.Limits.MaxClients = 1000 // Default
	}

	if c.Limits.MaxChannels <= 0 {
		c.Limits.MaxChannels = 100 // Default
	}

	if c.Limits.MaxNickLength <= 0 || c.Limits.MaxNickLength > 50 {
		c.Limits.MaxNickLength = 30 // Default
	}

	if c.Limits.PingTimeout <= 0 {
		c.Limits.PingTimeout = 300 // Default 5 minutes
	}

	if c.Limits.FloodLines <= 0 {
		c.Limits.FloodLines = 10 // Default
	}

	if c.Limits.FloodSeconds <= 0 {
		c.Limits.FloodSeconds = 60 // Default
	}

	// Validate channels
	for _, channelName := range c.Channels.AutoJoin {
		if !isChannelName(channelName) {
			return fmt.Errorf("invalid channel name in auto_join: %s", channelName)
		}
	}

	// Validate default modes
	validChannelModes := "mntisp"
	for _, mode := range c.Channels.DefaultModes {
		if mode != '+' && !strings.ContainsRune(validChannelModes, mode) {
			return fmt.Errorf("invalid default channel mode: %c", mode)
		}
	}

	// Validate founder mode
	validFounderModes := []string{"q", "a", "o", "h", "v"}
	foundValidMode := false
	for _, validMode := range validFounderModes {
		if c.Channels.FounderMode == validMode {
			foundValidMode = true
			break
		}
	}
	if !foundValidMode {
		return fmt.Errorf("invalid founder_mode '%s', must be one of: q (owner), a (admin), o (operator), h (halfop), v (voice)", c.Channels.FounderMode)
	}

	// Validate operators
	for i, oper := range c.Opers {
		if oper.Name == "" {
			return fmt.Errorf("operator %d: name cannot be empty", i)
		}
		if oper.Password == "" {
			return fmt.Errorf("operator %s: password cannot be empty", oper.Name)
		}
		if oper.Host == "" {
			return fmt.Errorf("operator %s: host cannot be empty", oper.Name)
		}
	}

	return nil
}

// SanitizeConfig applies safe defaults and sanitizes configuration values
func (c *Config) SanitizeConfig() {
	// Ensure reasonable limits
	if c.Limits.MaxClients > 10000 {
		c.Limits.MaxClients = 10000
	}

	if c.Limits.MaxChannels > 1000 {
		c.Limits.MaxChannels = 1000
	}

	// Set default founder mode if empty or invalid
	if c.Channels.FounderMode == "" {
		c.Channels.FounderMode = "o" // Default to operator
	}

	// Ensure reasonable string lengths
	if c.Limits.MaxTopicLength > 2048 {
		c.Limits.MaxTopicLength = 2048
	}

	if c.Limits.MaxKickLength > 2048 {
		c.Limits.MaxKickLength = 2048
	}

	// Ensure MOTD isn't too long
	if len(c.MOTD) > 50 {
		c.MOTD = c.MOTD[:50]
	}

	// Sanitize channel modes
	if c.Channels.DefaultModes == "" {
		c.Channels.DefaultModes = "+nt"
	}
}
