package config

import (
	"bytes"
	"fmt"
	"os"
	"path"
	"strconv"
	"strings"

	"github.com/creasty/defaults"
	"github.com/tidbcloud/pov-service/internal/pkg/log"
	"gopkg.in/yaml.v2"
)

type Secret struct {
	TiWorkloadAddress string
	TiWorkloadAk      string
	TiWorkloadSk      string

	TcmsAddress string
	TcmsAuth    string
	TcmsToken   string

	// DefTiDBCloudUserEmail string
	// DefTiDBCloudUserPwd   string

	RmsAddress string

	SendGridApiKey string
}

type DatabaseConfig struct {
	MaxOpenConns int `yaml:"maxOpenConns" default:"25"`
	MaxIdleConns int `yaml:"maxIdleConns" default:"5"`

	Host     string `yaml:"-" default:"localhost"`
	Port     int    `yaml:"-" default:"3306"`
	User     string `yaml:"-" default:"root"`
	Password string `yaml:"-"`
	Database string `yaml:"-" default:"tidbcloud_pov"`
	TLSMode  string `yaml:"tlsMode" default:"skip-verify"`
}

type Config struct {
	Port                           int    `yaml:"port"`
	TcmsWorkflowRunnerID           int64  `yaml:"tcmsWorkflowRunnerID"`
	EmailClusterCompleteTemplateID string `yaml:"emailClusterCompleteTemplateID"`
	EmailPrepareCompleteTemplateID string `yaml:"emailPrepareCompleteTemplateID"`
	EmailTrafficStartTemplateID    string `yaml:"emailTrafficStartTemplateID"`
	EmailCompleteTemplateID        string `yaml:"emailCompleteTemplateID"`
	EmailFromAddress               string `yaml:"emailFromAddress"`

	Database DatabaseConfig `yaml:"database"`
	Secret
}

func IsProdEnv() bool {
	return strings.ToUpper(os.Getenv("POV_ENV")) == "PROD"
}

func New(
	configPath, secretDir string,
) *Config {
	content, err := os.ReadFile(configPath)
	if err != nil {
		panic(fmt.Sprintf("read config file failed, err= %v", err))
	}

	config := &Config{}
	if err := yaml.Unmarshal(content, config); err != nil {
		panic(fmt.Sprintf("parse config file failed, err= %v", err))
	}
	defaults.MustSet(config)

	// read secret config
	readSecret := func(secret string) []byte {
		content, err = os.ReadFile(path.Join(secretDir, secret))
		if err != nil {
			panic(fmt.Sprintf("read secret config %s failed, err= %v", secret, err))
		}
		return bytes.TrimSpace(content)
	}
	config.TiWorkloadAddress = string(readSecret("tiworkloadAddress"))
	config.TiWorkloadAk = string(readSecret("tiworkloadAk"))
	config.TiWorkloadSk = string(readSecret("tiworkloadSk"))

	config.TcmsAddress = string(readSecret("tcmsAddress"))
	config.TcmsAuth = string(readSecret("tcmsAuth"))
	config.TcmsToken = string(readSecret("tcmsToken"))

	config.RmsAddress = string(readSecret("rmsAddress"))

	config.Database.Host = string(readSecret("dbHost"))
	port, err := strconv.ParseInt(string(readSecret("dbPort")), 10, 64)
	if err != nil {
		panic(fmt.Sprintf("parse dbPort failed, err= %v", err))
	}
	config.Database.Port = int(port)
	config.Database.User = string(readSecret("dbUser"))
	config.Database.Password = string(readSecret("dbPassword"))
	config.Database.Database = string(readSecret("dbDatabase"))

	config.SendGridApiKey = string(readSecret("sendGridApiKey"))

	// config.DefTiDBCloudUserEmail = string(readSecret("defTiDBCloudUserEmail"))
	// config.DefTiDBCloudUserPwd = string(readSecret("defTiDBCloudUserPwd"))

	log.Log.With("config", config).Infof("config loaded")
	return config
}
