package d_app

import (
	"github.com/go-playground/validator/v10"
	"os"
	"wdd.io/agent-common/logger"
	"wdd.io/agent-common/utils"
	"wdd.io/agent-deploy/z_dep"
)

var (
	DefaultCmiiBackendConfig  = &CmiiBackendConfig{}
	DefaultCmiiFrontendConfig = &CmiiFrontendConfig{}
	DefaultIngressConfig      = &IngressConfig{
		FrontendShortNameMaps:  FrontendShortNameMaps,
		BackendImageVersionMap: CmiiBackendAppMap,
	}

	log = logger.Log
)

type CmiiBackendConfig struct {
	z_dep.CommonEnvironmentConfig
	AppName      string `json:"app_name,omitempty" validate:"required"`
	ImageTag     string `json:"image_tag,omitempty" validate:"required"`
	Replicas     string `json:"replicas,omitempty"  validate:"required" default:"1"`
	NodePort     string `json:"node_port,omitempty"`
	NeedPvcCache bool   `json:"need_pvc_cache,omitempty"`
	CustomJvmOpt string `json:"custom_jvm_opt,omitempty"`
}

type CmiiFrontendConfig struct {
	z_dep.CommonEnvironmentConfig `json:"z___dep_._common_environment_config"`
	AppName                       string `json:"app_name,omitempty" validate:"required"`
	ImageTag                      string `json:"image_tag,omitempty" validate:"required"`
	Replicas                      string `json:"replicas,omitempty" validate:"required" default:"1"`
	ShortName                     string `json:"short_name,omitempty" validate:"required"`
	ClientId                      string
}

type CmiiSrsConfig struct {
	z_dep.CommonEnvironmentConfig
	RtmpPort              string
	WebRTCPort            string
	SrtPort               string
	WebApiPort            string
	MySQLK8sAdminPassword string
}

type IngressConfig struct {
	z_dep.CommonEnvironmentConfig
	FrontendShortNameMaps  map[string]string
	BackendImageVersionMap map[string]string `json:"backend_image_version_map,omitempty" validate:"required"`
}

func (backend *CmiiBackendConfig) BackendDeploy(common *z_dep.CommonEnvironmentConfig) bool {

	// copy
	utils.CopySameFields(common, backend)

	validate := validator.New()
	err := validate.Struct(backend)
	if err != nil {
		log.ErrorF("backend config validate error: %v\n", err)
		return false
	}

	if !z_dep.ParseEnvToApplyFile(backend, CmiiBackendDeploymentTemplate, z_dep.BackendApplyFilePath) {
		return false
	}
	if !z_dep.ParseEnvToApplyFile(backend, CmiiBackendServiceTemplate, z_dep.BackendApplyFilePath) {
		return false
	}

	// pvc
	if backend.NeedPvcCache {
		if !z_dep.ParseEnvToApplyFile(backend, CmiiBackendPVCTemplate, z_dep.BackendApplyFilePath) {
			return false
		}
	}

	return true
}

func (frontend *CmiiFrontendConfig) FrontendDeploy(common *z_dep.CommonEnvironmentConfig) bool {

	// copy
	utils.CopySameFields(common, frontend)

	validate := validator.New()
	err := validate.Struct(frontend)
	if err != nil {
		log.ErrorF("backend config validate error: %v\n", err)
		return false
	}

	if !z_dep.ParseEnvToApplyFile(frontend, CmiiFrontendDeploymentTemplate, z_dep.FrontendApplyFilePath) {
		return false
	}
	if !z_dep.ParseEnvToApplyFile(frontend, CmiiFrontendServiceTemplate, z_dep.FrontendApplyFilePath) {
		return false
	}

	return true
}

func (frontend *CmiiFrontendConfig) ConfigMapDeploy(commonEnv *z_dep.CommonEnvironmentConfig) bool {

	// copy
	utils.CopySameFields(commonEnv, frontend)

	// manual validate
	if frontend.ShortName == "" || frontend.ClientId == "" {
		log.ErrorF("short name or client id is empty !")
		return false
	}

	return z_dep.ParseEnvToApplyFile(frontend, CmiiFrontendConfigMapTemplate, z_dep.ConfigMapApplyFilePath)
}

func (ingress *IngressConfig) IngressDeploy(commonEnv *z_dep.CommonEnvironmentConfig) bool {
	// copy
	utils.CopySameFields(commonEnv, ingress)

	// manual validate
	if ingress.FrontendShortNameMaps == nil || len(ingress.FrontendShortNameMaps) == 0 {
		log.Error("frontend short name is empty !")
		return false
	}

	if ingress.BackendImageVersionMap == nil || len(ingress.BackendImageVersionMap) == 0 {
		log.Error("backend image version map is empty !")
		return false
	}

	if !z_dep.ParseEnvToApplyFile(ingress, CmiiFrontendIngressTemplate, z_dep.IngresApplyFilePath) {
		return false
	}

	if !z_dep.ParseEnvToApplyFile(ingress, CmiiBackendIngressTemplate, z_dep.IngresApplyFilePath) {
		return false
	}

	if !z_dep.ParseEnvToApplyFile(ingress, CmiiGatewayIngressTemplate, z_dep.IngresApplyFilePath) {
		return false
	}

	return true
}

func (srsConfig *CmiiSrsConfig) SRSDeploy(commonEnv *z_dep.CommonEnvironmentConfig) bool {
	// copy
	utils.CopySameFields(commonEnv, srsConfig)

	if srsConfig.MinioInnerIP == "" {
		log.Error("minio inner ip is nil !")
		return false
	}

	if !z_dep.ParseEnvToApplyFile(srsConfig, CmiiSrsTemplate, z_dep.SRSApplyFilePath) {
		return false
	}
	return true
}

func IngressDeploy(commonEnv *z_dep.CommonEnvironmentConfig) bool {
	if !commonEnv.ParseCommonEnvToApplyFile(CmiiFrontendIngressTemplate, z_dep.IngresApplyFilePath) {
		return false
	}

	if !commonEnv.ParseCommonEnvToApplyFile(CmiiBackendIngressTemplate, z_dep.IngresApplyFilePath) {
		return false
	}

	if !commonEnv.ParseCommonEnvToApplyFile(CmiiGatewayIngressTemplate, z_dep.IngresApplyFilePath) {
		return false
	}

	return true
}

func SRSDeploy(commonEnv *z_dep.CommonEnvironmentConfig) bool {
	os.Remove(z_dep.SRSApplyFilePath)
	return commonEnv.ParseCommonEnvToApplyFile(CmiiSrsTemplate, z_dep.SRSApplyFilePath)
}

func FrontendDefaultNginxDeploy(commonEnv *z_dep.CommonEnvironmentConfig) bool {
	return commonEnv.ParseCommonEnvToApplyFile(CmiiFrontendDefaultNginxConfTemplate, z_dep.FrontendApplyFilePath)
}
