package migration

import (
	"errors"
	"strings"
	"time"

	"github.com/samber/lo"
	"gorm.io/gorm"

	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/infra/repoimpl/schema"
)

// Remapping Standard and Performance SKUs for AWS ARM64 TiKV components.
var _ = AddDBMigrateRecord(
	"202504021200",
	func(db *gorm.DB) error {
		// Define timestamp and user from input
		timestamp := time.Now()

		return db.Transaction(func(tx *gorm.DB) error {
			// STEP 0: Delete all existing spu mappings
			var spuMappings []*schema.TierTierUnit
			if err := tx.Model(&schema.TierTierUnit{}).Find(&spuMappings).Error; err != nil {
				return err
			}
			for _, spuMapping := range spuMappings {
				spuMapping.TierUnitMapping.Items = lo.Filter(
					spuMapping.TierUnitMapping.Items,
					func(i *schema.TierUnitMappingItem, _ int) bool {
						return !strings.HasSuffix(i.SkuKey, ":Performance") && !strings.HasSuffix(i.SkuKey, ":Standard")
					},
				)
			}
			for _, spuMapping := range spuMappings {
				if err := tx.Save(spuMapping).Error; err != nil {
					return err
				}
			}

			// STEP 1: Fetch original ARM64 TiKV components with gp3 storage
			var originalUnits []schema.ComponentTierUnit

			subQuery := tx.Model(&schema.ComponentTierUnit{}).
				Select("component_tier_units.id").
				Joins("JOIN instance_types ON component_tier_units.instance_type_id = instance_types.id AND instance_types.cpu_arch = 'arm64'")

			if err := tx.Model(&schema.ComponentTierUnit{}).
				Where("id IN (?)", subQuery).
				Where("component_type LIKE ?", "%tikv%").
				Where("`key` LIKE ?", "%gp3%").
				Where("`key` NOT LIKE ?", "%:Standard").
				Where("`key` NOT LIKE ?", "%:Performance").
				Find(&originalUnits).Error; err != nil {
				return err
			}

			tierIDMap := lo.GroupBy(originalUnits, func(unit schema.ComponentTierUnit) uint64 {
				return unit.ComponentTierId
			})

			for tierID, units := range tierIDMap {
				// Find the tier_tier_unit record
				var tierTierUnit schema.TierTierUnit
				result := tx.Model(&schema.TierTierUnit{}).Where("component_tier_id = ?", tierID).First(&tierTierUnit)

				// Skip if not found
				if result.Error != nil {
					if errors.Is(result.Error, gorm.ErrRecordNotFound) {
						continue
					}
					return result.Error
				}

				// STEP 2: add Standard and Performance mappings for all original units.
				for _, unit := range units {
					standardKey := unit.Key + ":Standard"
					performanceKey := unit.Key + ":Performance"

					// Find existing items with the original key and add new variants
					for _, item := range tierTierUnit.TierUnitMapping.Items {
						if item.SkuKey == unit.Key {
							// Create standard entry
							standardItem := &schema.TierUnitMappingItem{
								TenantIDs:    item.TenantIDs,
								RegionNames:  item.RegionNames,
								ProviderName: item.ProviderName,
								SkuKey:       standardKey,
							}
							performanceItem := &schema.TierUnitMappingItem{
								TenantIDs:    []string{},
								RegionNames:  item.RegionNames,
								ProviderName: item.ProviderName,
								SkuKey:       performanceKey,
							}

							// Add new items
							tierTierUnit.TierUnitMapping.Items = append(
								tierTierUnit.TierUnitMapping.Items,
								standardItem,
								performanceItem,
							)
							break
						}
					}
				}

				// Update the record
				tierTierUnit.UpdatedAt = timestamp
				if err := tx.Save(&tierTierUnit).Error; err != nil {
					return err
				}
			}

			return nil
		})
	},
)
