package config

import (
	"fmt"
	"os"

	"gopkg.in/yaml.v3"
)

// Config holds application configuration
type Config struct {
	Server    *Server                      `yaml:"server"`
	Database  *Database                    `yaml:"database"`
	Auth      *Auth                        `yaml:"auth"`
	Providers map[string]map[string]string `yaml:"providers"`
	Debug     bool                         `yaml:"debug"`
}

func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
	type plain Config
	err := unmarshal((*plain)(c))
	if err != nil {
		return err
	}
	if c.Server == nil {
		return fmt.Errorf("server configuration is required")
	}
	if c.Database == nil {
		return fmt.Errorf("database configuration is required")
	}
	if c.Auth == nil {
		return fmt.Errorf("auth configuration is required")
	}
	if c.Providers == nil {
		return fmt.Errorf("at least one provider configuration is required")
	}
	return nil
}

// Server holds server configuration
type Server struct {
	Host string     `yaml:"host"`
	Port int        `yaml:"port"`
	Tls  *TlsConfig `yaml:"tls"`
}

func (c *Server) UnmarshalYAML(unmarshal func(interface{}) error) error {
	type plain Server
	err := unmarshal((*plain)(c))
	if err != nil {
		return err
	}
	if c.Host == "" {
		return fmt.Errorf("host is required")
	}
	if c.Port == 0 {
		c.Port = 443
	}
	if c.Tls == nil {
		return fmt.Errorf("TLS configuration is required")
	}
	return nil
}

// TlsConfig holds TLS configuration
type TlsConfig struct {
	Enabled  bool   `yaml:"enabled"`
	CertFile string `yaml:"cert_file"`
	KeyFile  string `yaml:"key_file"`
}

func (c *TlsConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
	type plain TlsConfig
	err := unmarshal((*plain)(c))
	if err != nil {
		return err
	}
	if (c.CertFile == "" || c.KeyFile == "") && c.Enabled {
		return fmt.Errorf("TLS cert file is required")
	}
	return nil
}

// Database holds database configuration
type Database struct {
	Type   string  `yaml:"type"`
	Sqlite *Sqlite `yaml:"sqlite"`
}

func (c *Database) UnmarshalYAML(unmarshal func(interface{}) error) error {
	type plain Database
	err := unmarshal((*plain)(c))
	if err != nil {
		return err
	}
	if c.Type == "" {
		return fmt.Errorf("database type is required")
	}
	if c.Type != "sqlite" && c.Type != "memory" {
		return fmt.Errorf("unsupported database type: %s", c.Type)
	}
	if c.Type == "sqlite" && c.Sqlite == nil {
		return fmt.Errorf("SQL database configuration is required")
	}
	return nil
}

// Sql holds SQL database configuration
type Sqlite struct {
	File string `yaml:"file"`
}

func (c *Sqlite) UnmarshalYAML(unmarshal func(interface{}) error) error {
	type plain Sqlite
	err := unmarshal((*plain)(c))
	if err != nil {
		return err
	}
	if c.File == "" {
		return fmt.Errorf("SQLite file is required")
	}
	return nil
}

// Auth holds authentication configuration
type Auth struct {
	PrivateKey      string `yaml:"private_key"`
	TokenDuration   int    `yaml:"token_duration"`
	CleanupInterval int    `yaml:"cleanup_interval"`
}

func (c *Auth) UnmarshalYAML(unmarshal func(interface{}) error) error {
	type plain Auth
	err := unmarshal((*plain)(c))
	if err != nil {
		return err
	}
	if c.PrivateKey == "" {
		return fmt.Errorf("private key is required")
	}
	if c.TokenDuration == 0 {
		c.TokenDuration = 3600 // Default to 1 hour
	}
	if c.CleanupInterval == 0 {
		c.CleanupInterval = 3600 // Default to 1 hour
	}
	return nil
}

func Load(configPath string) (*Config, error) {
	cnf := &Config{}
	b, err := os.ReadFile(configPath)
	if err != nil {
		return nil, err
	}
	err = yaml.Unmarshal(b, cnf)
	if err != nil {
		return nil, err
	}
	return cnf, nil
}
