package cvt

import (
	"fmt"

	"k8s.io/utils/ptr"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	apiv1 "github.com/tidbcloud/infra-provider/api/tidbcloud/cluster-server/v1"
)

func Strategy2PB(strategy cloudv1.ConfigChangeStrategy) apiv1.SetVersionAndConfigurationsRequest_Strategy {
	switch strategy {
	case cloudv1.ConfigChangeStrategyHotReload:
		return apiv1.SetVersionAndConfigurationsRequest_HOT_RELOAD
	case cloudv1.ConfigChangeStrategyRollingRestart:
		return apiv1.SetVersionAndConfigurationsRequest_ROLLING_RESTART
	case cloudv1.ConfigChangeStrategyChangeCMOnly:
		return apiv1.SetVersionAndConfigurationsRequest_CHANGE_CM_ONLY
	case cloudv1.ConfigChangeStrategyEnsureUpdateToTC:
		return apiv1.SetVersionAndConfigurationsRequest_ENSURE_UPDATE_TO_TC
	default:
		panic(fmt.Sprintf("invalid strategy: %s", strategy))
	}
}

func Strategy2CR(strategy apiv1.SetVersionAndConfigurationsRequest_Strategy) cloudv1.ConfigChangeStrategy {
	switch strategy {
	case apiv1.SetVersionAndConfigurationsRequest_HOT_RELOAD:
		return cloudv1.ConfigChangeStrategyHotReload
	case apiv1.SetVersionAndConfigurationsRequest_ROLLING_RESTART:
		return cloudv1.ConfigChangeStrategyRollingRestart
	case apiv1.SetVersionAndConfigurationsRequest_CHANGE_CM_ONLY:
		return cloudv1.ConfigChangeStrategyChangeCMOnly
	case apiv1.SetVersionAndConfigurationsRequest_ENSURE_UPDATE_TO_TC:
		return cloudv1.ConfigChangeStrategyEnsureUpdateToTC
	default:
		panic(fmt.Sprintf("invalid strategy: %s", strategy))
	}
}

func ConfigRevision2PB(cr *cloudv1.ConfigRevision) (*apiv1.ClusterVersion, []*apiv1.ComponentConfiguration, error) {
	if cr == nil {
		return nil, nil, nil
	}
	version := &apiv1.ClusterVersion{
		ClusterVersion:    cr.Spec.Version,
		ComponentVersions: nil,
	}
	var confs []*apiv1.ComponentConfiguration

	for tp := range componentsManagedByCluster {
		compoConf := cr.CompConfByType(tp)
		if compoConf == nil {
			continue
		}

		version.ComponentVersions = append(version.ComponentVersions, &apiv1.ClusterVersion_ComponentVersion{
			ComponentType: ComponentType2PB(tp),
			ImageRepo:     ptr.Deref(compoConf.BaseImage, ""),
			ImageTag:      ptr.Deref(compoConf.Tag, ""),
		})
		confContentBytes, err := compoConf.Config.MarshalTOML()
		if err != nil {
			return nil, nil, fmt.Errorf("unmarshal conf for component %s: %w", tp, err)
		}

		confs = append(confs, &apiv1.ComponentConfiguration{
			ConfigurationFileContents: string(confContentBytes),
			ComponentType:             ComponentType2PB(tp),
		})
	}

	return version, confs, nil
}
