package privatelinkservicemigration

import (
	"github.com/samber/lo"
	"google.golang.org/protobuf/types/known/timestamppb"
	"gorm.io/gorm"

	globaldedicatedv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/dedicated/v1"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/entity"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/infra/repoimpl/schema"
)

func privatelinkServiceMigrationEnToModel(migration *entity.PrivateLinkServiceMigration) *schema.PrivateLinkServiceMigration {
	plsm := &schema.PrivateLinkServiceMigration{
		Model: gorm.Model{
			ID: uint(migration.Id),
		},
		SourceClusterID: migration.SourceClusterId,
		TargetClusterID: migration.TargetClusterId,
		RunMode:         migration.RunMode.String(),
		State:           migration.State.String(),
		Message:         migration.Message,
		OrganizationID:  migration.OrganizationId,
		ProjectID:       migration.ProjectId,
	}
	for _, migrationTidbGroup := range migration.MigrationTidbGroups {
		plsm.MigrationTidbGroups = append(plsm.MigrationTidbGroups, privatelinkServiceMigrationTidbGroupEnToModel(migrationTidbGroup))
	}
	if migration.MigrationPlan != nil {
		plsm.MigrationPlanDisableRecreate = lo.ToPtr(migration.MigrationPlan.DisableRecreatePrivateLinkServiceForSourceTidbGroup)
		plsm.MigrationPlanTimeoutSeconds = lo.ToPtr(int(*migration.MigrationPlan.TimeoutSeconds))
	}
	if migration.CreateTime != nil {
		plsm.CreatedAt = migration.CreateTime.AsTime()
	}
	if migration.UpdateTime != nil {
		plsm.UpdatedAt = migration.UpdateTime.AsTime()
	}

	return plsm
}

func privatelinkServiceMigrationModelToEn(migration *schema.PrivateLinkServiceMigration) *entity.PrivateLinkServiceMigration {
	plsm := &entity.PrivateLinkServiceMigration{
		Id:              uint64(migration.ID),
		CreateTime:      timestamppb.New(migration.CreatedAt),
		UpdateTime:      timestamppb.New(migration.UpdatedAt),
		SourceClusterId: migration.SourceClusterID,
		TargetClusterId: migration.TargetClusterID,
		RunMode:         runModeToEntity(migration.RunMode),
		State:           stateToEntity(migration.State),
		Message:         migration.Message,
		OrganizationId:  migration.OrganizationID,
		ProjectId:       migration.ProjectID,
	}
	for _, migrationTidbGroup := range migration.MigrationTidbGroups {
		plsm.MigrationTidbGroups = append(plsm.MigrationTidbGroups, privatelinkServiceMigrationTidbGroupModelToEn(migrationTidbGroup))
	}
	if migration.MigrationPlanDisableRecreate != nil || migration.MigrationPlanTimeoutSeconds != nil {
		if plsm.MigrationPlan == nil {
			plsm.MigrationPlan = &globaldedicatedv1.PrivateLinkServiceMigration_MigrationPlan{}
		}
		if migration.MigrationPlanDisableRecreate != nil {
			plsm.MigrationPlan.DisableRecreatePrivateLinkServiceForSourceTidbGroup = lo.FromPtr(migration.MigrationPlanDisableRecreate)
		} else {
			plsm.MigrationPlan.DisableRecreatePrivateLinkServiceForSourceTidbGroup = false
		}
		if migration.MigrationPlanTimeoutSeconds != nil {
			plsm.MigrationPlan.TimeoutSeconds = lo.ToPtr(int32(*migration.MigrationPlanTimeoutSeconds))
		}
	}
	return plsm
}

func privatelinkServiceMigrationTidbGroupModelToEn(migrationTidbGroup *schema.MigrationTidbGroup) *entity.MigrationTidbGroup {
	mtg := &entity.MigrationTidbGroup{
		State:             stateToEntity(migrationTidbGroup.State),
		SourceTidbGroupId: migrationTidbGroup.SourceTidbGroupID,
		TargetTidbGroupId: migrationTidbGroup.TargetTidbGroupID,
		Message:           migrationTidbGroup.Message,
	}
	if migrationTidbGroup.StartTime != nil {
		mtg.StartTime = timestamppb.New(*migrationTidbGroup.StartTime)
	}
	if migrationTidbGroup.CompleteTime != nil {
		mtg.CompleteTime = timestamppb.New(*migrationTidbGroup.CompleteTime)
	}

	return mtg
}

func privatelinkServiceMigrationTidbGroupEnToModel(migrationTidbGroup *entity.MigrationTidbGroup) *schema.MigrationTidbGroup {
	mtg := &schema.MigrationTidbGroup{
		SourceTidbGroupID: migrationTidbGroup.SourceTidbGroupId,
		TargetTidbGroupID: migrationTidbGroup.TargetTidbGroupId,
		State:             migrationTidbGroup.State.String(),
		Message:           migrationTidbGroup.Message,
	}

	if migrationTidbGroup.StartTime != nil {
		mtg.StartTime = lo.ToPtr(migrationTidbGroup.StartTime.AsTime())
	}
	if migrationTidbGroup.CompleteTime != nil {
		mtg.CompleteTime = lo.ToPtr(migrationTidbGroup.CompleteTime.AsTime())
	}

	return mtg
}

func migrationTidbGroupEnToModel(migrationId uint64, migrationTidbGroup *entity.MigrationTidbGroup) *schema.MigrationTidbGroup {
	mtg := &schema.MigrationTidbGroup{
		MigrationID:       migrationId,
		SourceTidbGroupID: migrationTidbGroup.SourceTidbGroupId,
		TargetTidbGroupID: migrationTidbGroup.TargetTidbGroupId,
		State:             migrationTidbGroup.State.String(),
		Message:           migrationTidbGroup.Message,
	}

	if migrationTidbGroup.StartTime != nil {
		mtg.StartTime = lo.ToPtr(migrationTidbGroup.StartTime.AsTime())
	}
	if migrationTidbGroup.CompleteTime != nil {
		mtg.CompleteTime = lo.ToPtr(migrationTidbGroup.CompleteTime.AsTime())
	}

	return mtg
}

func migrationTidbGroupModelToEn(migrationTidbGroup *schema.MigrationTidbGroup) *entity.MigrationTidbGroup {
	mtg := &entity.MigrationTidbGroup{
		State:             stateToEntity(migrationTidbGroup.State),
		SourceTidbGroupId: migrationTidbGroup.SourceTidbGroupID,
		TargetTidbGroupId: migrationTidbGroup.TargetTidbGroupID,
		Message:           migrationTidbGroup.Message,
	}
	if migrationTidbGroup.StartTime != nil {
		mtg.StartTime = timestamppb.New(*migrationTidbGroup.StartTime)
	}
	if migrationTidbGroup.CompleteTime != nil {
		mtg.CompleteTime = timestamppb.New(*migrationTidbGroup.CompleteTime)
	}

	return mtg
}

func runModeToEntity(runMode string) globaldedicatedv1.PrivateLinkServiceMigration_RunMode {
	return globaldedicatedv1.PrivateLinkServiceMigration_RunMode(globaldedicatedv1.PrivateLinkServiceMigration_RunMode_value[runMode])
}

func stateToEntity(state string) globaldedicatedv1.PrivateLinkServiceMigration_State {
	return globaldedicatedv1.PrivateLinkServiceMigration_State(globaldedicatedv1.PrivateLinkServiceMigration_State_value[state])
}
