package config

import (
	"os"
	"time"

	"gopkg.in/yaml.v2"
)

type Config struct {
	ListenAddr          string            `yaml:"listenAddr"`
	StripeKey           string            `yaml:"stripeKey"`
	StripeWebhookSecret string            `yaml:"stripeWebhookSecret"`
	Containers          []ContainerConfig `yaml:"containers"`
	Global              GlobalConfig      `yaml:"global"`
}

type GlobalConfig struct {
	ReconcileInterval   time.Duration   `yaml:"reconcile_interval"`
	HealthCheckInterval time.Duration   `yaml:"health_check_interval"`
	CleanupInterval     time.Duration   `yaml:"cleanup_interval"`
	Networks            []NetworkConfig `yaml:"networks"`
}

type ContainerConfig struct {
	Name          string            `yaml:"name"`
	Image         string            `yaml:"image"`
	Command       []string          `yaml:"command,omitempty"`
	Env           map[string]string `yaml:"env,omitempty"`
	RestartPolicy string            `yaml:"restart_policy,omitempty"`
	HealthCheck   *HealthCheck      `yaml:"health_check,omitempty"`
	Resources     *ResourceConfig   `yaml:"resources,omitempty"`
	Volumes       []VolumeMount     `yaml:"volumes,omitempty"`
	Ports         []PortMapping     `yaml:"ports,omitempty"`
	Networks      []string          `yaml:"networks,omitempty"`
	NetworkMode   string            `yaml:"network_mode,omitempty"`
	Labels        map[string]string `yaml:"labels,omitempty"`
	Dependencies  []string          `yaml:"dependencies,omitempty"`
	User          string            `yaml:"user,omitempty"`
	WorkingDir    string            `yaml:"working_dir,omitempty"`
	Privileged    bool              `yaml:"privileged,omitempty"`
}

type HealthCheck struct {
	Test        []string      `yaml:"test"`
	Interval    time.Duration `yaml:"interval"`
	Timeout     time.Duration `yaml:"timeout"`
	Retries     int           `yaml:"retries"`
	StartPeriod time.Duration `yaml:"start_period"`
}

type ResourceConfig struct {
	CPUShares  int64  `yaml:"cpu_shares,omitempty"`
	Memory     string `yaml:"memory,omitempty"`
	MemorySwap string `yaml:"memory_swap,omitempty"`
	CPUPeriod  int64  `yaml:"cpu_period,omitempty"`
	CPUQuota   int64  `yaml:"cpu_quota,omitempty"`
	CPUsetCPUs string `yaml:"cpuset_cpus,omitempty"`
	CPUsetMems string `yaml:"cpuset_mems,omitempty"`
}

type VolumeMount struct {
	Source      string `yaml:"source"`
	Target      string `yaml:"target"`
	Type        string `yaml:"type,omitempty"`
	ReadOnly    bool   `yaml:"read_only,omitempty"`
	Consistency string `yaml:"consistency,omitempty"`
}

type PortMapping struct {
	HostPort      string `yaml:"host_port"`
	ContainerPort string `yaml:"container_port"`
	Protocol      string `yaml:"protocol,omitempty"`
	HostIP        string `yaml:"host_ip,omitempty"`
}

type NetworkConfig struct {
	Name       string            `yaml:"name"`
	Driver     string            `yaml:"driver"`
	Internal   bool              `yaml:"internal,omitempty"`
	EnableIPv6 bool              `yaml:"enable_ipv6,omitempty"`
	IPAM       *IPAMConfig       `yaml:"ipam,omitempty"`
	Options    map[string]string `yaml:"options,omitempty"`
	Labels     map[string]string `yaml:"labels,omitempty"`
}

type IPAMConfig struct {
	Driver  string      `yaml:"driver,omitempty"`
	Options []string    `yaml:"options,omitempty"`
	Config  []IPAMRange `yaml:"config,omitempty"`
}

type IPAMRange struct {
	Subnet     string `yaml:"subnet,omitempty"`
	IPRange    string `yaml:"ip_range,omitempty"`
	Gateway    string `yaml:"gateway,omitempty"`
	AuxAddress string `yaml:"aux_address,omitempty"`
}

func LoadConfig(path string) (*Config, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		return nil, err
	}

	var config Config
	if err := yaml.Unmarshal(data, &config); err != nil {
		return nil, err
	}

	return &config, nil
}
