package domain

import (
	"github.com/tidbcloud/config-center/proto/config_center"
	"github.com/tidbcloud/dataflow-service/idl/pbgen/proto/dataflow"
	bizerr_wrapper "github.com/tidbcloud/dataflow-service/pkg/bizerr-wrapper"
	infraapi "github.com/tidbcloud/dataflow-service/pkg/infra-api"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/pkgv2/bizerr"
)

type ConfigComponent string

const (
	ConfigComponentBackup            ConfigComponent = "backup"
	ConfigComponentRestore           ConfigComponent = "restore"
	ConfigComponentTiCDC             ConfigComponent = "ticdc"
	ConfigComponentLightning         ConfigComponent = "tidb-lightning"
	ConfigComponentDataMigration     ConfigComponent = "data-migration"
	ConfigComponentCompactBackupBR   ConfigComponent = "compact-backup-br"
	ConfigComponentCompactBackupTiKV ConfigComponent = "compact-backup-tikv"
)

type GetConfigVersionReq struct {
	ClusterID uint64
	Component ConfigComponent
}

// GetTiCDCClusterVersionAndImageTagReq is the request for reading the version
// and effective image tag of a TiCDC cluster component from the config center.
type GetTiCDCClusterVersionAndImageTagReq struct {
	TiCDCClusterID uint64
}

// GetTiCDCClusterVersionAndImageTagResp is the response carrying the version
// and effective image tag of a TiCDC cluster component.
type GetTiCDCClusterVersionAndImageTagResp struct {
	Version  string
	ImageTag string
}

type ConfigVersionInfo struct {
	BaseImage      string
	Tag            string
	Config         string
	UpdateStrategy config_center.UpdateStrategy
}

func (c *ConfigVersionInfo) ToDPConfiguration() *cloudv1.DPConfiguration {
	return &cloudv1.DPConfiguration{
		BaseImage: c.BaseImage,
		Tag:       c.Tag,
		Config:    c.Config,
	}
}

type InitConfigVersionReq struct {
	ClusterID     uint64
	TenantID      uint64
	Component     ConfigComponent
	Version       string
	CloudProvider CloudProviderType
}

type UpdateConfigVersionReq struct {
	ClusterID      uint64
	Component      ConfigComponent
	Version        *string
	TemplateID     *uint64
	CustomParams   map[string]*dataflow.ParamItem
	CustomImageTag *string
}

type UpdateVersionReq struct {
	ClusterID uint64
	Component ConfigComponent
	Version   string
}

type GetDefaultVersionReq struct {
	Component       ConfigComponent
	ClusterVersion  string
	ClusterProvider string
	Region          string
	TenantID        uint64
}

type DefaultVersionInfo struct {
	Version string
	Source  string
}

func DataflowConfigFile2Component(fileType dataflow.ConfigFileType) (ConfigComponent, bizerr.BizError) {
	switch fileType {
	case dataflow.ConfigFileType_BACKUP_FILE:
		return ConfigComponentBackup, nil
	case dataflow.ConfigFileType_RESTORE_FILE:
		return ConfigComponentRestore, nil
	case dataflow.ConfigFileType_TICDC_FILE:
		return ConfigComponentTiCDC, nil
	case dataflow.ConfigFileType_COMPACT_BACKUP_BR_FILE:
		return ConfigComponentCompactBackupBR, nil
	case dataflow.ConfigFileType_COMPACT_BACKUP_TIKV_FILE:
		return ConfigComponentCompactBackupTiKV, nil
	default:
		return "", bizerr_wrapper.NewInvalidInputError("unsupported config file type %s", fileType.String())
	}
}

func ConfigComponent2ConfigFormat(component ConfigComponent) (config_center.Format, bizerr.BizError) {
	switch component {
	case ConfigComponentBackup, ConfigComponentRestore, ConfigComponentCompactBackupBR, ConfigComponentCompactBackupTiKV:
		// backup/restore/compact-backup use yaml in gitops, but they are unserialized as json in infra provider
		// ops-portal has no file format, so we change to use json format
		return config_center.Format_JSON, nil
	case ConfigComponentTiCDC, ConfigComponentLightning, ConfigComponentDataMigration:
		return config_center.Format_TOML, nil
	default:
		return 0, bizerr_wrapper.NewInvalidInputError("unsupported component %s", component)
	}
}

// MergeToCompactBackupConfiguration merges BR and TiKV configurations into CompactBackupConfiguration
func MergeToCompactBackupConfiguration(brConfig, tikvConfig *ConfigVersionInfo) *infraapi.CompactBackupConfiguration {
	config := &infraapi.CompactBackupConfiguration{}

	// Use BR config for base image, tag, and config
	if brConfig != nil {
		config.BaseImage = brConfig.BaseImage
		config.Tag = brConfig.Tag
		config.Config = brConfig.Config
	}

	// Use TiKV config for TiKV image and version
	if tikvConfig != nil {
		config.TiKVImage = tikvConfig.BaseImage
		config.TiKVVersion = tikvConfig.Tag
	}

	return config
}
