package config

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/pelletier/go-toml"
)

type Config struct {
	Store    StoreConfig    `toml:"Store"`
	Honeypot HoneypotConfig `toml:"Honeypot"`
	Frontend FrontendConfig `toml:"Frontend"`
	Ports    PortsConfig    `toml:"Ports"`
	SMTP     SMTPConfig     `toml:"SMTP"`
}
type StoreConfig struct {
	Type        string              `toml:"Type"`
	EnableCache bool                `toml:"EnableCache"`
	Postgres    PostgresStoreConfig `toml:"Postgres"`
}

type PostgresStoreConfig struct {
	DSN string `toml:"DSN"`
}

type HoneypotConfig struct {
	ListenAddr    string  `toml:"ListenAddr"`
	LogLevel      string  `toml:"LogLevel"`
	HostKeyPath   string  `toml:"HostKeyPath"`
	ThrottleSpeed float64 `toml:"ThrottleSpeed"`
}

type FrontendConfig struct {
	ListenAddr      string                 `toml:"ListenAddr"`
	LogLevel        string                 `toml:"LogLevel"`
	AccessLogEnable bool                   `toml:"AccessLogEnable"`
	Autocert        FrontendAutocertConfig `toml:"Autocert"`
}

type FrontendAutocertConfig struct {
	Enable       bool     `toml:"Enable"`
	Email        string   `toml:"Email"`
	Domains      []string `toml:"Domains"`
	CacheDir     string   `toml:"CacheDir"`
	RedirectHTTP bool     `toml:"RedirectHTTP"`
}

type PortsConfig struct {
	Enable   bool     `toml:"Enable"`
	Addr     string   `toml:"Addr"`
	TCPPorts []string `toml:"TCPPorts"`
	UDPPorts []string `toml:"UDPPorts"`
}

type SMTPConfig struct {
	Enable        bool   `toml:"Enable"`
	Addr          string `toml:"Addr"`
	EnableMetrics bool   `toml:"EnableMetrics"`
}

func FromReader(r io.Reader) (Config, error) {
	var c Config

	// Set some defaults
	c.Honeypot.ListenAddr = ":2222"
	c.Honeypot.LogLevel = "INFO"
	c.Frontend.ListenAddr = ":8080"
	c.Frontend.LogLevel = "INFO"
	c.Frontend.AccessLogEnable = true
	c.SMTP.Addr = ":25"

	// Read from config
	decoder := toml.NewDecoder(r)
	if err := decoder.Decode(&c); err != nil {
		return c, fmt.Errorf("unable to parse config: %w", err)
	}

	//c.readEnv()

	return c, nil
}

func FromString(s string) (Config, error) {
	r := strings.NewReader(s)
	return FromReader(r)
}

func FromFile(path string) (Config, error) {
	f, err := os.Open(path)
	if err != nil {
		return Config{}, fmt.Errorf("error opening config: %w", err)
	}
	defer f.Close()

	return FromReader(f)
}
