package flags

import (
	"fmt"
	"net/url"
	"os"
	"strings"

	"github.com/common-nighthawk/go-figure"
	"gopkg.in/alecthomas/kingpin.v2"
	"gopkg.in/ini.v1"
)

var (
	// apm
	ConfigServer        = kingpin.Flag("config-server", "The URL of the endpoint to send traces to").Envar("CONFIG_SERVER").Default("http://10.0.16.250:18080").String()
	DataServer          = kingpin.Flag("data-server", "The URL of the endpoint to send traces to").Envar("DATA_SERVER").Default("http://10.0.16.250:18080").String()
	DumpApps            = kingpin.Flag("dump", "Dump app snap").Short('d').Default("false").Bool()
	DumpRules           = kingpin.Flag("dr", "Dump rule snap").Default("false").Bool()
	PrintFormat         = kingpin.Flag("output", "Output format (table|json)").Short('o').Default("table").String()
	Version             = kingpin.Flag("version", "show app version").Short('v').Bool()
	LogLevel            = kingpin.Flag("log-level", "Log level").Envar("LOG_LEVEL").Default("info").String()
	ConsoleLog          = kingpin.Flag("console-log", "Console log").Envar("CONSOLE_LOG").Default("false").Bool()
	EbpfFilePath        = kingpin.Flag("ebpf-path", "Set ebpf file path").Envar("EBPF_FILE").Default("").String()
	CommonIni           = kingpin.Flag("common.ini", "Set ebpf file path").Envar("COMMON_INI").Default("/opt/cloudwise/omniagent/conf/common.ini").String()
	ServerPrefix        = kingpin.Flag("server-prefix", "server-prefix").Envar("SERVER_PREFIX").Default("").String()
	DisableRegisterHost = kingpin.Flag("disable-reg-host", "Disable reg host").Default("false").Envar("DISABLE_REG_HOST").Bool()
	// agent
	DisableE2ETracing   = kingpin.Flag("disable-e2e-tracing", "Disable e2e tracing").Default("true").Envar("DISABLE_E2E_TRACING").Bool()
	DisableStackTracing = kingpin.Flag("disable-stack-tracing", "Disable stack tracing").Default("true").Envar("DISABLE_STACK_TRACING").Bool()
	LicenseKey          = kingpin.Flag("license-key", "Apm API key").Default("J45Engw88NeHUZ4Q7qNsK8L47FTH**QvgW113IEnsNaBNMR5zZ**oj/g!!!!").Envar("LICENSE_KEY").String()
	RunInContainer      = kingpin.Flag("run-in-container", "run in container").Default("false").Envar("RUN_IN_CONTAINER").Bool()
	RunInOmniagent      = kingpin.Flag("run-in-omniagent", "run in omniagent").Default("false").Envar("RUN_IN_OMNIAGENT").Bool()

	ListenAddress     = kingpin.Flag("listen", "Listen address - ip:port or :port").Default("0.0.0.0:8123").Envar("LISTEN").String()
	CgroupRoot        = kingpin.Flag("cgroupfs-root", "The mount point of the host cgroupfs root").Default("/sys/fs/cgroup").Envar("CGROUPFS_ROOT").String()
	DisableLogParsing = kingpin.Flag("disable-log-parsing", "Disable container log parsing").Default("true").Envar("DISABLE_LOG_PARSING").Bool()
	DisablePinger     = kingpin.Flag("disable-pinger", "Don't ping upstreams").Default("false").Envar("DISABLE_PINGER").Bool()
	DisableL7Tracing  = kingpin.Flag("disable-l7-tracing", "Disable L7 tracing").Default("false").Envar("DISABLE_L7_TRACING").Bool()

	ExternalNetworksWhitelist = kingpin.
		Flag("track-public-network", "Allow track connections to the specified IP networks, all private networks are allowed by default (e.g., Y.Y.Y.Y/mask)").
		Envar("TRACK_PUBLIC_NETWORK").
		Default("0.0.0.0/0").
		Strings()
	EphemeralPortRange = kingpin.Flag("ephemeral-port-range", "Destination and Listen TCP ports from this range will be skipped").Default("").Envar("EPHEMERAL_PORT_RANGE").String()

	Provider          = kingpin.Flag("provider", "`provider` label for `node_cloud_info` metric").Envar("PROVIDER").String()
	Region            = kingpin.Flag("region", "`region` label for `node_cloud_info` metric").Envar("REGION").String()
	AvailabilityZone  = kingpin.Flag("availability-zone", "`availability_zone` label for `node_cloud_info` metric").Envar("AVAILABILITY_ZONE").String()
	InstanceType      = kingpin.Flag("instance-type", "`instance_type` label for `node_cloud_info` metric").Envar("INSTANCE_TYPE").String()
	InstanceLifeCycle = kingpin.Flag("instance-life-cycle", "`instance_life_cycle` label for `node_cloud_info` metric").Envar("INSTANCE_LIFE_CYCLE").String()
	LogPerSecond      = kingpin.Flag("log-per-second", "The number of logs per second").Default("10.0").Envar("LOG_PER_SECOND").Float64()
	LogBurst          = kingpin.Flag("log-burst", "The maximum number of tokens that can be consumed in a single call to allow").Default("100").Envar("LOG_BURST").Int()

	CollectorEndpoint  = kingpin.Flag("collector-endpoint", "A base endpoint URL for metrics, traces, logs, and profiles").Envar("COLLECTOR_ENDPOINT").URL()
	ApiKey             = kingpin.Flag("api-key", "Coroot API key").Envar("API_KEY").String()
	MetricsEndpoint    = kingpin.Flag("metrics-endpoint", "The URL of the endpoint to send metrics to").Envar("METRICS_ENDPOINT").URL()
	TracesEndpoint     = kingpin.Flag("traces-endpoint", "The URL of the endpoint to send traces to").Envar("TRACES_ENDPOINT").URL()
	LogsEndpoint       = kingpin.Flag("logs-endpoint", "The URL of the endpoint to send logs to").Envar("LOGS_ENDPOINT").URL()
	ProfilesEndpoint   = kingpin.Flag("profiles-endpoint", "The URL of the endpoint to send profiles to").Envar("PROFILES_ENDPOINT").URL()
	InsecureSkipVerify = kingpin.Flag("insecure-skip-verify", "whether to skip verifying the certificate or not").Envar("INSECURE_SKIP_VERIFY").Default("false").Bool()

	ScrapeInterval = kingpin.Flag("scrape-interval", "How often to gather metrics from the agent").Default("15s").Envar("SCRAPE_INTERVAL").Duration()
	WalDir         = kingpin.Flag("wal-dir", "Path to where the agent stores data (e.g. the metrics Write-Ahead Log)").Default("/tmp/coroot-node-agent").Envar("WAL_DIR").String()

	HostDirPathPrefix = kingpin.Flag("host-dir-path-prefix", "Set the prefix of path about the mount point of the host directory").Envar("HOST_DIR_PATH_PREFIX").Default("").String()
	FuseTryMax        = kingpin.Flag("fuse_try_max", "The maximum number of the fuse operation try").Default("3").Envar("FUSE_TRY_MAX").Int()
	// debug
	Test = kingpin.Flag("test", "Only test").Default("false").Envar("TEST").Bool()
	// op 新增配置
	SysTag = kingpin.Flag("sys-tag", "sys tag").Envar("CW_SYS").Default("").String()
	// l7
	MysqlDefault = kingpin.Flag("mysql-default", "Default MySQL protocol when port-based detection fails").Envar("MYSQL_DEFAULT").Default("mysql").String()

	// 端口白名单配置
	MysqlPortWhitelist   = kingpin.Flag("mysql-ports", "Comma-separated list of ports to identify as MySQL").Envar("MYSQL_PORTS").Default("").String()
	MariadbPortWhitelist = kingpin.Flag("mariadb-ports", "Comma-separated list of ports to identify as MariaDB").Envar("MARIADB_PORTS").Default("").String()
	//APP注册到DOOP
	RegisterAppToDoop = kingpin.Flag("register-app-to-doop", "Register the app-info to the doop").Default("false").Envar("REGISTER_APP_TO_DOOP").Bool()
	//是否向平台发送网络数据
	SendNetData = kingpin.Flag("send-net-data", "Send the net data to platform").Default("false").Envar("SEND_NET_DATA").Bool()
)

var AgentName = "euspace"
var AgentVersion = "0.0.1"
var GitCommit = ""
var BuildDate = ""

func GetString(fl *string) string {
	if fl == nil {
		return ""
	}
	return *fl
}

func init() {
	if strings.HasSuffix(os.Args[0], ".test") {
		return
	}

	kingpin.HelpFlag.Short('h').Hidden()
	kingpin.Parse()
	if *Test {
		euspace := figure.NewFigure("TEST", "", true)
		euspace.Print()
	} else {
		euspace := figure.NewColorFigure("Euspace", "slant", "blue", true)
		euspace.Print()
	}
	if *Version {
		ShowVersion()
	}
	if *DumpApps {
		DumpTableFeatures(*PrintFormat)
	}
	if *DumpRules {
		DumpRuleTableFeatures(*PrintFormat)
	}
	if *CollectorEndpoint != nil {
		u := *CollectorEndpoint
		if *MetricsEndpoint == nil {
			*MetricsEndpoint = u.JoinPath("/v1/metrics")
		}
		if *TracesEndpoint == nil {
			*TracesEndpoint = u.JoinPath("/v1/traces")
		}
		if *LogsEndpoint == nil {
			*LogsEndpoint = u.JoinPath("/v1/logs")
		}
		if *ProfilesEndpoint == nil {
			*ProfilesEndpoint = u.JoinPath("/v1/profiles")
		}
	}

	if *MetricsEndpoint != nil {
		*ListenAddress = "127.0.0.1:10300"
	}

	// set ServerPrefix
	// set ConfigServer
	// set DataServer
	if *RunInOmniagent {
		iniData, err := ini.Load(*CommonIni)
		if err == nil && iniData != nil {
			*ServerPrefix = "/apm"
			*ConfigServer = iniData.Section("common").Key("config_server").String()
			*DataServer = iniData.Section("common").Key("data_server").String()
		}
	}

	// set TracesEndpoint
	if *TracesEndpoint == nil && *DataServer != "" {
		if !strings.HasPrefix(*DataServer, "http") {
			*DataServer = fmt.Sprintf("http://%s", *DataServer)
		}
		dataServer, err := url.Parse(*DataServer)
		if err == nil && dataServer != nil {
			*TracesEndpoint = dataServer.JoinPath(*ServerPrefix + "/api/v2/data/receive")
		}
	}

	// set tiny-agent config
	//nativeConf := utils.GetDefaultAgentsPath("NativeAgent", "conf", "agent.properties")
	//confData, err := ini.Load(nativeConf)
	//if err == nil {
	//	configServer := *ConfigServer
	//	if !strings.HasPrefix(*ConfigServer, "http") {
	//		configServer = fmt.Sprintf("http://%s", *ConfigServer)
	//	}
	//	confData.Section(ini.DEFAULT_SECTION).Key("ConfigDomain").SetValue(configServer + *ServerPrefix)
	//	confData.Section(ini.DEFAULT_SECTION).Key("SendDomain").SetValue(*DataServer + *ServerPrefix)
	//	err = confData.SaveTo(nativeConf)
	//	if err != nil {
	//		klog.Error(err)
	//	}
	//}

	if *RunInContainer {
		if *HostDirPathPrefix == "" {
			*HostDirPathPrefix = "/host"
		}
	} else {
		*HostDirPathPrefix = ""
	}

	// 初始化端口白名单
	InitPortWhitelists()
}

func ShowVersion() {
	fmt.Printf("%-20s %-8s\n", "Name:", AgentName)
	fmt.Printf("%-20s %-8s\n", "Version:", AgentVersion)
	fmt.Printf("%-20s %-8s\n", "Commit:", GitCommit)
	fmt.Printf("%-20s %-8s\n", "Date:", BuildDate)
	os.Exit(0)
}
