package config

import (
	"encoding/json"
	"flag"
	"os"
	"strings"
)

type Config struct {
	HttpPort uint
	Tiflash  struct {
		Port                  uint
		Namespace             string
		ServiceDNS            string
		ConfigMap             string
		DefaultPool           string
		TemplatePool          string
		StatefulSetNameFormat string
		PeerServiceNameFormat string
		HPANameFormat         string
	}
}

func (c *Config) String() {
	data, err := json.MarshalIndent(c, "", "  ")
	if err != nil {
		panic(err)
	}
	os.Stdout.Write(data)
}

func (c *Config) StatefulSetName(pool string) string {
	return formatPoolName(c.Tiflash.StatefulSetNameFormat, pool)
}

func (c *Config) PeerServiceName(pool string) string {
	return formatPoolName(c.Tiflash.PeerServiceNameFormat, pool)
}

func (c *Config) HPAName(pool string) string {
	return formatPoolName(c.Tiflash.HPANameFormat, pool)
}

func formatPoolName(format, pool string) string {
	return strings.ReplaceAll(format, "{POOL}", pool)
}

var defaultConfig = Config{
	HttpPort: 8080,
	Tiflash: struct {
		Port                  uint
		Namespace             string
		ServiceDNS            string
		ConfigMap             string
		DefaultPool           string
		TemplatePool          string
		StatefulSetNameFormat string
		PeerServiceNameFormat string
		HPANameFormat         string
	}{
		Port:                  3930,
		Namespace:             "tidb-serverless",
		ServiceDNS:            "tiflash-{POOL}-{INDEX}.tiflash-manager-{POOL}-peer.tidb-serverless.svc.cluster.local",
		ConfigMap:             "tiflash-manager-config",
		DefaultPool:           "main",
		TemplatePool:          "main",
		StatefulSetNameFormat: "tiflash-{POOL}",
		PeerServiceNameFormat: "tiflash-manager-{POOL}-peer",
		HPANameFormat:         "tiflash-{POOL}",
	},
}

func Parsed() *Config {
	httpPort := flag.Uint("http-port", defaultConfig.HttpPort, "HTTP server port")
	tiflashPort := flag.Uint("tiflash-port", defaultConfig.Tiflash.Port, "TiFlash port")
	tiflashNamespace := flag.String("tiflash-namespace", defaultConfig.Tiflash.Namespace, "TiFlash namespace")
	tiflashServiceDNS := flag.String("tiflash-service-dns", defaultConfig.Tiflash.ServiceDNS, "TiFlash service DNS format")
	tiflashConfigMap := flag.String("tiflash-config-map", defaultConfig.Tiflash.ConfigMap, "TiFlash config map name")
	tiflashDefaultPool := flag.String("tiflash-default-pool", defaultConfig.Tiflash.DefaultPool, "TiFlash default pool name")
	tiflashTemplatePool := flag.String("tiflash-template-pool", defaultConfig.Tiflash.TemplatePool, "TiFlash template pool name used to create new pools")
	tiflashStatefulSetNameFormat := flag.String("tiflash-statefulset-name-format", defaultConfig.Tiflash.StatefulSetNameFormat, "TiFlash StatefulSet name format, use {POOL} as placeholder")
	tiflashPeerServiceNameFormat := flag.String("tiflash-peer-service-name-format", defaultConfig.Tiflash.PeerServiceNameFormat, "TiFlash peer Service name format, use {POOL} as placeholder")
	tiflashHPANameFormat := flag.String("tiflash-hpa-name-format", defaultConfig.Tiflash.HPANameFormat, "TiFlash HPA name format, use {POOL} as placeholder")
	flag.Parse()

	defaultConfig.HttpPort = *httpPort
	defaultConfig.Tiflash.Port = *tiflashPort
	defaultConfig.Tiflash.Namespace = *tiflashNamespace
	defaultConfig.Tiflash.ServiceDNS = *tiflashServiceDNS
	defaultConfig.Tiflash.ConfigMap = *tiflashConfigMap
	defaultConfig.Tiflash.DefaultPool = *tiflashDefaultPool
	defaultConfig.Tiflash.TemplatePool = *tiflashTemplatePool
	defaultConfig.Tiflash.StatefulSetNameFormat = *tiflashStatefulSetNameFormat
	defaultConfig.Tiflash.PeerServiceNameFormat = *tiflashPeerServiceNameFormat
	defaultConfig.Tiflash.HPANameFormat = *tiflashHPANameFormat

	return &defaultConfig
}

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

	if err := json.Unmarshal(data, c); err != nil {
		return err
	}

	return nil
}
