package common

import (
	"fmt"

	opv2 "github.com/pingcap/tidb-operator/api/v2/core/v1alpha1"
	opv1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1"
	"github.com/tidbcloud/config-service/sdk/api"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
)

// ComponentContext contains information needed to render a Component Group CR.
type ComponentContext struct {
	Config                    *api.ComponentOutput
	SecondConfig              *api.ComponentOutput
	Version                   string
	Resources                 ComponentResources
	allowedCN                 string
	StorageClassName          string
	VolumeAttributesClassName *string
	Replicas                  *int32
	InstanceType              string
	StorageSize               resource.Quantity
	NodeSelector              map[string]string
	Tolerations               []corev1.Toleration
}

type ComponentResources struct {
	Requests opv2.ResourceRequirements
	Limits   opv2.ResourceRequirements
}

func (compCtx *ComponentContext) computePDConfig(cluster *cloudv1.Cluster) (cf opv2.ConfigFile, err error) {
	conf := opv1alpha1.NewPDConfig()
	conf.GenericConfig.MP = compCtx.Config.Config.MP
	conf.Set("dashboard.public-path-prefix", fmt.Sprintf("/proxy/cluster/%s/pd/dashboard", cluster.Name))
	conf.Set("security.cert-allowed-cn", []string{compCtx.allowedCN})
	if cluster.Spec.Cluster.TiFlash.Replicas > 0 {
		conf.Set("replication.enable-placement-rules", true)
	}
	configBytes, err := conf.MarshalTOML()
	if err != nil {
		return cf, fmt.Errorf("failed to marshal pd config: %w", err)
	}
	return opv2.ConfigFile(configBytes), nil
}

func (compCtx *ComponentContext) computeTiKVConfig() (cf opv2.ConfigFile, err error) {
	conf := opv1alpha1.NewTiKVConfig()
	conf.GenericConfig.MP = compCtx.Config.Config.MP
	conf.Set("security.cert-allowed-cn", []string{compCtx.allowedCN})
	configBytes, err := conf.MarshalTOML()
	if err != nil {
		return cf, fmt.Errorf("failed to marshal tikv config: %w", err)
	}
	return opv2.ConfigFile(configBytes), nil
}

func (compCtx *ComponentContext) computeTiFlashConfig() (cf, proxyCfg opv2.ConfigFile, err error) {
	conf := opv1alpha1.NewTiFlashConfig()
	conf.Common.MP = compCtx.Config.Config.MP
	conf.Proxy.MP = compCtx.SecondConfig.Config.MP
	conf.Common.Set("security.cert_allowed_cn", []string{compCtx.allowedCN})
	conf.Proxy.Set("security.cert-allowed-cn", []string{compCtx.allowedCN})
	commonConfigBytes, err := conf.Common.MarshalTOML()
	if err != nil {
		return cf, proxyCfg, fmt.Errorf("failed to marshal tiflash common config: %w", err)
	}
	proxyConfigBytes, err := conf.Proxy.MarshalTOML()
	if err != nil {
		return cf, proxyCfg, fmt.Errorf("failed to marshal tiflash proxy config: %w", err)
	}
	return opv2.ConfigFile(commonConfigBytes), opv2.ConfigFile(proxyConfigBytes), nil
}
