package export

import (
	clusterngv1beta "github.com/tidbcloud/cluster-service-ng/api/cluster-service-ng/v1beta"

	globalngv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/nextgen/v1"
	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/infra/repoimpl/schema"
)

func SchemaExportToRegionalExport(in *schema.Export) *clusterngv1beta.Export {
	if in == nil {
		return nil
	}

	out := &clusterngv1beta.Export{
		ExportId:    in.ExportId,
		ClusterId:   in.ClusterId,
		SnapshotTso: in.SnapshotTso,
		Username:    in.Username,
		Password:    in.EncryptedPassword,
		TidbGroupId: in.TidbGroupId,
	}
	if in.ExportOptions != nil {
		out.ExportOptions = schemaExportOptionsToRegional(in.ExportOptions)
	}
	if in.CloudStorage != nil {
		out.CloudStorage = schemaCloudStorageToRegional(in.CloudStorage)
	}
	return out
}

func schemaExportOptionsToRegional(m *schema.ExportOptions) *clusterngv1beta.ExportOptions {
	if m == nil {
		return nil
	}
	out := &clusterngv1beta.ExportOptions{}
	switch m.FileType {
	case globalngv1.ExportOptions_SQL.String():
		out.FileType = clusterngv1beta.ExportOptions_SQL
	case globalngv1.ExportOptions_CSV.String():
		out.FileType = clusterngv1beta.ExportOptions_CSV
		out.CsvFormat = schemaCSVFormatToRegional(m.CSVFormat)
	case globalngv1.ExportOptions_PARQUET.String():
		out.FileType = clusterngv1beta.ExportOptions_PARQUET
		out.ParquetFormat = schemaParquetFormatToRegional(m.ParquetFormat)
	default:
		out.FileType = clusterngv1beta.ExportOptions_FILE_TYPE_UNSPECIFIED
	}
	switch m.Compression {
	case globalngv1.ExportOptions_GZIP.String():
		out.Compression = clusterngv1beta.ExportOptions_GZIP
	case globalngv1.ExportOptions_SNAPPY.String():
		out.Compression = clusterngv1beta.ExportOptions_SNAPPY
	case globalngv1.ExportOptions_ZSTD.String():
		out.Compression = clusterngv1beta.ExportOptions_ZSTD
	case globalngv1.ExportOptions_NONE.String():
		out.Compression = clusterngv1beta.ExportOptions_NONE
	default:
		out.Compression = clusterngv1beta.ExportOptions_COMPRESSION_TYPE_UNSPECIFIED
	}
	if m.Filter != nil {
		out.Filter = schemaExportOptionsFilterToRegional(m.Filter)
	}
	out.EscapeBackslash = m.EscapeBackslash
	return out
}

func schemaExportOptionsFilterToRegional(m *schema.ExportOptionsFilter) *clusterngv1beta.ExportOptions_Filter {
	if m == nil {
		return nil
	}
	out := &clusterngv1beta.ExportOptions_Filter{}
	if m.Sql != nil {
		out.Type = &clusterngv1beta.ExportOptions_Filter_Sql{Sql: *m.Sql}
		return out
	}
	if m.Table != nil {
		out.Type = &clusterngv1beta.ExportOptions_Filter_Table_{
			Table: &clusterngv1beta.ExportOptions_Filter_Table{
				Patterns:   m.Table.Patterns,
				Where:      m.Table.Where,
				Partitions: m.Table.Partitions,
			},
		}
		return out
	}
	return nil
}

func schemaParquetFormatToRegional(m *schema.ExportOptionsParquetFormat) *clusterngv1beta.ExportOptions_ParquetFormat {
	if m == nil {
		return nil
	}
	return &clusterngv1beta.ExportOptions_ParquetFormat{
		Compression: clusterngv1beta.ExportParquetCompressionType_Enum(
			clusterngv1beta.ExportParquetCompressionType_Enum_value[m.Compression],
		),
	}
}

func schemaCSVFormatToRegional(m *schema.ExportOptionsCSVFormat) *clusterngv1beta.ExportOptions_CSVFormat {
	if m == nil {
		return nil
	}
	return &clusterngv1beta.ExportOptions_CSVFormat{
		Separator:  m.Separator,
		SkipHeader: m.SkipHeader,
		Delimiter:  m.Delimiter,
		NullValue:  m.NullValue,
		Dialect:    csvDialectToRegional(m.Dialect),
	}
}

func csvDialectToRegional(dialect *string) *clusterngv1beta.ExportOptions_ExportCSVDialect_Enum {
	if dialect == nil {
		return nil
	}
	value, ok := clusterngv1beta.ExportOptions_ExportCSVDialect_Enum_value[*dialect]
	if !ok {
		return nil
	}
	result := clusterngv1beta.ExportOptions_ExportCSVDialect_Enum(value)
	return &result
}

func schemaCloudStorageToRegional(m *schema.CloudStorage) *clusterngv1beta.CloudStorage {
	if m == nil {
		return nil
	}
	out := &clusterngv1beta.CloudStorage{}
	switch m.Type {
	case globalngv1.CloudStorageType_S3.String():
		out.Type = clusterngv1beta.CloudStorageType_S3
	case globalngv1.CloudStorageType_GCS.String():
		out.Type = clusterngv1beta.CloudStorageType_GCS
	case globalngv1.CloudStorageType_AZURE_BLOB.String():
		out.Type = clusterngv1beta.CloudStorageType_AZURE_BLOB
	case globalngv1.CloudStorageType_OSS.String():
		out.Type = clusterngv1beta.CloudStorageType_OSS
	default:
		out.Type = clusterngv1beta.CloudStorageType_CLOUD_STORAGE_TYPE_UNSPECIFIED
	}
	switch out.Type {
	case clusterngv1beta.CloudStorageType_S3:
		out.Storage = &clusterngv1beta.CloudStorage_S3{S3: schemaS3ToRegional(m.S3)}
	case clusterngv1beta.CloudStorageType_GCS:
		out.Storage = &clusterngv1beta.CloudStorage_Gcs{Gcs: schemaGCSToRegional(m.Gcs)}
	case clusterngv1beta.CloudStorageType_AZURE_BLOB:
		out.Storage = &clusterngv1beta.CloudStorage_AzureBlob{AzureBlob: schemaAzureBlobToRegional(m.AzureBlob)}
	case clusterngv1beta.CloudStorageType_OSS:
		out.Storage = &clusterngv1beta.CloudStorage_Oss{Oss: schemaOSSToRegional(m.Oss)}
	}
	return out
}

func schemaS3ToRegional(m *schema.S3CloudStorage) *clusterngv1beta.S3CloudStorage {
	if m == nil {
		return nil
	}
	out := &clusterngv1beta.S3CloudStorage{Uri: m.Uri}
	switch m.AuthType {
	case globalngv1.S3CloudStorage_ROLE_ARN.String():
		out.AuthType = clusterngv1beta.S3CloudStorage_ROLE_ARN
		out.Auth = &clusterngv1beta.S3CloudStorage_RoleArn{RoleArn: m.RoleArn}
	case globalngv1.S3CloudStorage_ACCESS_KEY.String():
		out.AuthType = clusterngv1beta.S3CloudStorage_ACCESS_KEY
		out.Auth = &clusterngv1beta.S3CloudStorage_AccessKey_{
			AccessKey: &clusterngv1beta.S3CloudStorage_AccessKey{
				Id:     m.AccessKey.Id,
				Secret: m.AccessKey.Secret,
			},
		}
	default:
		out.AuthType = clusterngv1beta.S3CloudStorage_S3_AUTH_TYPE_UNSPECIFIED
	}
	return out
}

func schemaGCSToRegional(m *schema.GCSCloudStorage) *clusterngv1beta.GCSCloudStorage {
	if m == nil {
		return nil
	}
	out := &clusterngv1beta.GCSCloudStorage{Uri: m.Uri}
	switch m.AuthType {
	case globalngv1.GCSCloudStorage_SERVICE_ACCOUNT_KEY.String():
		out.AuthType = clusterngv1beta.GCSCloudStorage_SERVICE_ACCOUNT_KEY
		out.Auth = &clusterngv1beta.GCSCloudStorage_ServiceAccountKey{ServiceAccountKey: m.ServiceAccountKey}
	default:
		out.AuthType = clusterngv1beta.GCSCloudStorage_GCS_AUTH_TYPE_UNSPECIFIED
	}
	return out
}

func schemaAzureBlobToRegional(m *schema.AzureBlobCloudStorage) *clusterngv1beta.AzureBlobCloudStorage {
	if m == nil {
		return nil
	}
	out := &clusterngv1beta.AzureBlobCloudStorage{Uri: m.Uri}
	switch m.AuthType {
	case globalngv1.AzureBlobCloudStorage_SAS_TOKEN.String():
		out.AuthType = clusterngv1beta.AzureBlobCloudStorage_SAS_TOKEN
		out.Auth = &clusterngv1beta.AzureBlobCloudStorage_SasToken{SasToken: m.SasToken}
	default:
		out.AuthType = clusterngv1beta.AzureBlobCloudStorage_AZURE_BLOB_AUTH_TYPE_UNSPECIFIED
	}
	return out
}

func schemaOSSToRegional(m *schema.OSSCloudStorage) *clusterngv1beta.OSSCloudStorage {
	if m == nil {
		return nil
	}
	out := &clusterngv1beta.OSSCloudStorage{Uri: m.Uri}
	switch m.AuthType {
	case globalngv1.OSSCloudStorage_ACCESS_KEY.String():
		out.AuthType = clusterngv1beta.OSSCloudStorage_ACCESS_KEY
		out.Auth = &clusterngv1beta.OSSCloudStorage_AccessKey_{
			AccessKey: &clusterngv1beta.OSSCloudStorage_AccessKey{
				Id:     m.AccessKey.Id,
				Secret: m.AccessKey.Secret,
			},
		}
	case globalngv1.OSSCloudStorage_ROLE_ARN.String():
		out.AuthType = clusterngv1beta.OSSCloudStorage_ROLE_ARN
		out.Auth = &clusterngv1beta.OSSCloudStorage_RoleArn{RoleArn: m.RoleArn}
	default:
		out.AuthType = clusterngv1beta.OSSCloudStorage_OSS_AUTH_TYPE_UNSPECIFIED
	}
	return out
}
