package deploy

import (
	"context"

	"github.com/go-gormigrate/gormigrate/v2"
	"gorm.io/gorm"
)

func init() {
	registerMigrateRecord((*migrator).migrateDeleteBuckets20251201)
}

// cleanup internal/data bucket for shared pools
// this ops only delete buckets after applying lifecycle rules.
func (m *migrator) migrateDeleteBuckets20251201(ctx context.Context) gormigrate.MigrateFunc {
	return func(db *gorm.DB) error {

		return InvokeRunMigrateWithRetry(ctx, func() error {
			return db.Transaction(func(tx *gorm.DB) error {
				// 	sharedPools, err := m.sharedPoolRepo.List(ctx, nil, true)
				// 	if err != nil {
				// 		return fmt.Errorf("failed to list shared pools: %w", err)
				// 	}

				// 	if len(sharedPools) == 0 {
				// 		tilog.PlainInfo("no shared pools found, skip migration")
				// 		return nil
				// 	}

				// 	// Use concurrent execution with limited concurrency
				// 	const maxConcurrency = 10
				// 	semaphore := make(chan struct{}, maxConcurrency)
				// 	var wg sync.WaitGroup
				// 	var mu sync.Mutex
				// 	var errors []error

				// 	for _, sharedPool := range sharedPools {
				// 		// only clean up buckets for deleted shared pools
				// 		if sharedPool.DeletedAt == nil {
				// 			tilog.Info(ctx, "shared pool is not deleted, skip", zap.String("sharedPoolId", sharedPool.GetId()))
				// 			continue
				// 		}

				// 		wg.Add(1)
				// 		go func(sp *entity.SharedPool) {
				// 			defer wg.Done()

				// 			// Acquire semaphore
				// 			semaphore <- struct{}{}
				// 			defer func() { <-semaphore }()

				// 			// only 15 days after deletion
				// 			if time.Since(*sp.DeletedAt) < 15*24*time.Hour {
				// 				tilog.Info(ctx, "shared pool deleted less than 15 days ago, skip delete data bucket", zap.String("sharedPoolId", sp.GetId()))
				// 			} else {
				// 				// delete data bucket
				// 				tilog.Info(ctx, "deleting data bucket", zap.String("sharedPoolId", sp.GetId()))
				// 				if err := m.deleteBucket(ctx, entity.GetDataBucketId(sp.GetId(), sp.GetObjectStorage().GetRegion()), sp.GetDataplaneName()); err != nil {
				// 					tilog.Error(ctx, "failed to delete data bucket", zap.String("sharedPoolId", sp.GetId()), zap.Error(err))
				// 					mu.Lock()
				// 					errors = append(errors, fmt.Errorf("failed to delete data bucket for %s: %w", sp.GetId(), err))
				// 					mu.Unlock()
				// 				}
				// 			}

				// 			// only 7 days after deletion
				// 			if time.Since(*sp.DeletedAt) < 7*24*time.Hour {
				// 				tilog.Info(ctx, "shared pool deleted less than 7 days ago, skip delete internal bucket", zap.String("sharedPoolId", sp.GetId()))
				// 			} else {
				// 				// delete internal bucket
				// 				tilog.Info(ctx, "deleting internal bucket", zap.String("sharedPoolId", sp.GetId()))
				// 				if err := m.deleteBucket(ctx, entity.GetInternalBucketId(sp.GetId(), sp.GetInternalStorage().GetRegion()), sp.GetDataplaneName()); err != nil {
				// 					tilog.Error(ctx, "failed to delete internal bucket", zap.String("sharedPoolId", sp.GetId()), zap.Error(err))
				// 					mu.Lock()
				// 					errors = append(errors, fmt.Errorf("failed to delete internal bucket for %s: %w", sp.GetId(), err))
				// 					mu.Unlock()
				// 				}
				// 			}

				// 			tilog.Info(ctx, "finished deleting buckets", zap.String("sharedPoolId", sp.GetId()))
				// 		}(sharedPool)
				// 	}

				// 	// Wait for all goroutines to complete
				// 	wg.Wait()

				// 	// Log summary of errors if any
				// 	if len(errors) > 0 {
				// 		tilog.Error(ctx, "some bucket deletions failed", zap.Int("errorCount", len(errors)))
				// 		for _, err := range errors {
				// 			tilog.Error(ctx, "bucket deletion error", zap.Error(err))
				// 		}
				// 		// Don't return error to allow migration to succeed even if some buckets fail
				// 	}

				return nil
			})
		})
	}
}

// func (m *migrator) deleteBucket(ctx context.Context, bucketId, dataplaneId string) error {

// 	_, err := m.dataplaneClient.GetBucket(ctx, &dplanemgrv1.GetBucketRequest{
// 		DataplaneId: dataplaneId,
// 		BucketId:    bucketId,
// 	})

// 	if err != nil {
// 		if status.Code(err) == codes.NotFound {
// 			tilog.Info(ctx, "bucket not found, skip delete", zap.String("bucketId", bucketId))
// 			return nil
// 		}
// 		tilog.Error(ctx, "failed to get bucket", zap.String("bucketId", bucketId), zap.Error(err))
// 		return fmt.Errorf("failed to get bucket: %w", err)
// 	}

// 	// check if lifecycle rules exist
// 	rules, err := m.dataplaneClient.GetLifecycleRules(ctx, &dplanemgrv1.GetLifecycleRulesRequest{
// 		DataplaneId: dataplaneId,
// 		BucketId:    bucketId,
// 	})

// 	if err != nil {
// 		tilog.Error(ctx, "failed to get lifecycle rules", zap.String("bucketId", bucketId), zap.Error(err))
// 		return fmt.Errorf("failed to get lifecycle rules: %w", err)
// 	}

// 	// check the clean up lifecycle rule exists
// 	if len(rules.GetRules()) != 1 {
// 		tilog.Info(ctx, "managed by other lifecycle rules, skip delete", zap.String("bucketId", bucketId))
// 		return nil
// 	}

// 	// clean up rule id is "cleanup-bucket-rule"
// 	// "tiflashgc" means tiflash gc rule created by tiflash itself, is also ok to delete bucket
// 	if rules.GetRules()[0].GetId() != "cleanup-bucket-rule" && rules.GetRules()[0].GetId() != "tiflashgc" {
// 		tilog.Info(ctx, "cleanup lifecycle rule not found, skip delete", zap.String("bucketId", bucketId))
// 		return nil
// 	} // delete bucket
// 	_, err = m.dataplaneClient.DeleteBucket(ctx, &dplanemgrv1.DeleteBucketRequest{
// 		DataplaneId: dataplaneId,
// 		BucketId:    bucketId,
// 	})
// 	if err != nil {
// 		return fmt.Errorf("failed to delete bucket %s: %w", bucketId, err)
// 	}
// 	tilog.Info(ctx, "bucket deleted successfully", zap.String("bucketId", bucketId))

// 	return nil
// }
