package config

import (
	"fmt"
	"os"
	"sync"

	"freeleaps.com/gitea-webhook-ambassador/internal/logger"
	"github.com/go-playground/validator/v10"
	"gopkg.in/yaml.v2"
)

// Configuration holds application configuration
type Configuration struct {
	Server struct {
		Port         int    `yaml:"port" validate:"required,gt=0"`
		WebhookPath  string `yaml:"webhookPath" validate:"required"`
		SecretHeader string `yaml:"secretHeader" default:"Authorization"`
		SecretKey    string `yaml:"secretKey"`
	} `yaml:"server"`

	Jenkins struct {
		URL      string `yaml:"url" validate:"required,url"`
		Username string `yaml:"username"`
		Token    string `yaml:"token"`
		Timeout  int    `yaml:"timeout" default:"30"`
	} `yaml:"jenkins"`

	Database struct {
		Path string `yaml:"path" validate:"required"` // Path to SQLite database file
	} `yaml:"database"`

	Logging struct {
		Level  string `yaml:"level" default:"info" validate:"oneof=debug info warn error"`
		Format string `yaml:"format" default:"text" validate:"oneof=text json"`
		File   string `yaml:"file"`
	} `yaml:"logging"`

	Worker struct {
		PoolSize     int `yaml:"poolSize" default:"10" validate:"gt=0"`
		QueueSize    int `yaml:"queueSize" default:"100" validate:"gt=0"`
		MaxRetries   int `yaml:"maxRetries" default:"3" validate:"gte=0"`
		RetryBackoff int `yaml:"retryBackoff" default:"1" validate:"gt=0"`
	} `yaml:"worker"`

	EventCleanup struct {
		Interval    int `yaml:"interval" default:"3600"`
		ExpireAfter int `yaml:"expireAfter" default:"7200"`
	} `yaml:"eventCleanup"`
}

// ProjectConfig represents the configuration for a specific repository
type ProjectConfig struct {
	DefaultJob     string            `yaml:"defaultJob"`
	BranchJobs     map[string]string `yaml:"branchJobs,omitempty"`
	BranchPatterns []BranchPattern   `yaml:"branchPatterns,omitempty"`
}

// BranchPattern defines a pattern-based branch to job mapping
type BranchPattern struct {
	Pattern string `yaml:"pattern"`
	Job     string `yaml:"job"`
}

var (
	config      Configuration
	configMutex sync.RWMutex
	validate    = validator.New()
)

// Load reads and parses the configuration file
func Load(file string) error {
	logger.Debug("Loading configuration from file: %s", file)
	f, err := os.Open(file)
	if err != nil {
		return fmt.Errorf("cannot open config file: %v", err)
	}
	defer f.Close()

	var newConfig Configuration
	decoder := yaml.NewDecoder(f)
	if err := decoder.Decode(&newConfig); err != nil {
		return fmt.Errorf("cannot decode config: %v", err)
	}

	setDefaults(&newConfig)

	if err := validate.Struct(newConfig); err != nil {
		return fmt.Errorf("invalid configuration: %v", err)
	}

	logger.Debug("Configuration loaded successfully - Server.SecretKey length: %d", len(newConfig.Server.SecretKey))

	configMutex.Lock()
	config = newConfig
	configMutex.Unlock()

	return nil
}

// Get returns a copy of the current configuration
func Get() Configuration {
	configMutex.RLock()
	defer configMutex.RUnlock()
	return config
}

// Update atomically updates the configuration
func Update(newConfig Configuration) {
	configMutex.Lock()
	config = newConfig
	configMutex.Unlock()
}

func setDefaults(config *Configuration) {
	if config.Server.SecretHeader == "" {
		config.Server.SecretHeader = "X-Gitea-Signature"
	}
	if config.Jenkins.Timeout == 0 {
		config.Jenkins.Timeout = 30
	}
	if config.Worker.PoolSize == 0 {
		config.Worker.PoolSize = 10
	}
	if config.Worker.QueueSize == 0 {
		config.Worker.QueueSize = 100
	}
	if config.Worker.MaxRetries == 0 {
		config.Worker.MaxRetries = 3
	}
	if config.Worker.RetryBackoff == 0 {
		config.Worker.RetryBackoff = 1
	}
	if config.EventCleanup.Interval == 0 {
		config.EventCleanup.Interval = 3600
	}
	if config.EventCleanup.ExpireAfter == 0 {
		config.EventCleanup.ExpireAfter = 7200
	}
	if config.Logging.Level == "" {
		config.Logging.Level = "info"
	}
	if config.Logging.Format == "" {
		config.Logging.Format = "text"
	}
}
