package z_dep

import (
	"bytes"
	"fmt"
	"github.com/go-playground/validator/v10"
	"path/filepath"
	"text/template"
	"wdd.io/agent-common/assert"
	"wdd.io/agent-common/logger"
	"wdd.io/agent-common/utils"
)

var (
	K8sDashboardApplyFilePath = ""
	EmqxApplyFilePath         = ""
	MongoApplyFilePath        = ""
	RabbitMQApplyFilePath     = ""
	RedisApplyFilePath        = ""
	MySQLApplyFilePath        = ""
	NacosApplyFilePath        = ""
	PVCApplyFilePath          = ""
	NfsApplyFilePath          = ""
	NfsTestApplyFilePath      = ""
	BackendApplyFilePath      = ""
	FrontendApplyFilePath     = ""
	SRSApplyFilePath          = ""
	IngresApplyFilePath       = ""
	ConfigMapApplyFilePath    = ""

	K8sDashboardApplyFileName = "k8s-dashboard.yaml"
	EmqxApplyFileName         = "k8s-emqx.yaml"
	MongoApplyFileName        = "k8s-mongo.yaml"
	RabbitMQApplyFileName     = "k8s-rabbitmq.yaml"
	RedisApplyFileName        = "k8s-redis.yaml"
	MySQLApplyFileName        = "k8s-mysql.yaml"
	NacosApplyFileName        = "k8s-nacos.yaml"
	PVCApplyFileName          = "k8s-pvc.yaml"
	NfsApplyFileName          = "k8s-nfs.yaml"
	NfsTestApplyFileName      = "k8s-nfs-test.yaml"
	SRSApplyFileName          = "k8s-srs.yaml"
	IngresApplyFileName       = "k8s-ingress.yaml"
	ConfigMapApplyFileName    = "k8s-configmap.yaml"
	FrontendApplyFileName     = "k8s-frontend.yaml"
	BackendApplyFileName      = "k8s-backend.yaml"

	log      = logger.Log
	Asserter = assert.Asserter
)

type CommonEnvironmentConfig struct {
	WebIP                       string `json:"web_ip,omitempty" valid:"required"`                           //A1C1IP
	WebPort                     string `json:"web_port,omitempty" valid:"required"`                         //A1C1JS
	HarborIPOrCustomImagePrefix string `json:"harbor_ip_or_custom_image_prefix,omitempty" valid:"required"` //A1C2IP

	HarborPort      string `json:"harbor_port,omitempty" valid:"required"` // default 8033
	Namespace       string `json:"namespace,omitempty" valid:"required"`   // SUPREME
	TagVersion      string `json:"tag_version,omitempty" valid:"required"` // KIMMY
	TenantEnv       string `json:"tenant_env,omitempty"`                   // TENANT_ENV 只在内部使用
	MinioPublicIP   string `json:"minio_public_ip,omitempty"`              // M2C1IP
	MinioInnerIP    string `json:"minio_inner_ip,omitempty"`               // M2D2IP
	NFSServerIP     string `json:"nfs_server_ip,omitempty"`                // N1C2IP
	ApplyFilePrefix string
}

func (env *CommonEnvironmentConfig) ValidateAndUniform() bool {
	validate := validator.New()
	err := validate.Struct(env)
	if err != nil {
		fmt.Printf("backend config validate error: %v\n", err)
		return false
	}

	// uniform all
	if env.MinioInnerIP == "" {
		env.MinioInnerIP = env.HarborIPOrCustomImagePrefix
	}

	if env.MinioPublicIP == "" {
		env.MinioPublicIP = env.WebIP
	}

	return true
}

func (env *CommonEnvironmentConfig) ParseCommonEnvToApplyFile(applyTemplate string, applyFilePath string) bool {

	return ParseEnvToApplyFile(env, applyTemplate, applyFilePath)
}

func (env *CommonEnvironmentConfig) GenerateApplyFilePath() {

	Asserter.NotEmpty(env.ApplyFilePrefix, "apply file prefix is empty!")

	K8sDashboardApplyFilePath = filepath.Join(env.ApplyFilePrefix, K8sDashboardApplyFileName)
	EmqxApplyFilePath = filepath.Join(env.ApplyFilePrefix, EmqxApplyFileName)
	MongoApplyFilePath = filepath.Join(env.ApplyFilePrefix, MongoApplyFileName)
	RabbitMQApplyFilePath = filepath.Join(env.ApplyFilePrefix, RabbitMQApplyFileName)
	RedisApplyFilePath = filepath.Join(env.ApplyFilePrefix, RedisApplyFileName)
	MySQLApplyFilePath = filepath.Join(env.ApplyFilePrefix, MySQLApplyFileName)
	NacosApplyFilePath = filepath.Join(env.ApplyFilePrefix, NacosApplyFileName)
	PVCApplyFilePath = filepath.Join(env.ApplyFilePrefix, PVCApplyFileName)
	NfsApplyFilePath = filepath.Join(env.ApplyFilePrefix, NfsApplyFileName)
	NfsTestApplyFilePath = filepath.Join(env.ApplyFilePrefix, NfsTestApplyFileName)
	BackendApplyFilePath = filepath.Join(env.ApplyFilePrefix, BackendApplyFileName)
	FrontendApplyFilePath = filepath.Join(env.ApplyFilePrefix, FrontendApplyFileName)
	SRSApplyFilePath = filepath.Join(env.ApplyFilePrefix, SRSApplyFileName)
	IngresApplyFilePath = filepath.Join(env.ApplyFilePrefix, IngresApplyFileName)
	ConfigMapApplyFilePath = filepath.Join(env.ApplyFilePrefix, ConfigMapApplyFileName)

}

func ParseEnvToApplyFile(environment any, applyTemplate string, applyFilePath string) bool {

	randomString := utils.GenerateRandomString(8, false)

	// Deployment
	tmpl, err := template.New(randomString).Parse(applyTemplate)
	if err != nil {
		log.ErrorF("parse template error: %v", err)
		return false
	}
	// 应用数据并打印结果
	var result bytes.Buffer
	err = tmpl.Execute(&result, environment)
	if err != nil {
		log.ErrorF("[ParseEnvToApplyFile] - [%s] template execute error: %v", applyFilePath, err)
		return false
	}

	// append to file
	if !utils.AppendK8sYamlWithSplitLineToFile(result.String(), applyFilePath) {
		return false
	}

	return true
}
