package crrf

import (
	"fmt"
	"time"

	. "github.com/tidbcloud/dataflow-service-e2e/cases"
	"github.com/tidbcloud/dataflow-service-e2e/cases/dedicated/common"
	"github.com/tidbcloud/dataflow-service-e2e/internal/config"
	. "github.com/tidbcloud/dataflow-service-e2e/internal/model"
)

// crrfAutoPiTRTriggerCase tests the Auto-CRRF PiTR-trigger path:
// Enable DR → Enable PiTR → snapshot → CRRF auto-enables → disable PiTR → CRRF auto-disables.
type crrfAutoPiTRTriggerCase struct {
	BaseCase
	backupValidator *common.BackupValidator
	crrfValidator   *common.CRRFValidator
	cloudProvider   CloudProviderType
}

func NewCRRFAutoPiTRTriggerCase(cloudProvider CloudProviderType) E2ECase {
	return &crrfAutoPiTRTriggerCase{cloudProvider: cloudProvider}
}

func (m *crrfAutoPiTRTriggerCase) Name() string {
	return fmt.Sprintf("%sCRRFAutoPiTRTrigger", m.cloudProvider)
}

func (m *crrfAutoPiTRTriggerCase) Tags() map[string]string {
	return map[string]string{TagKeyDomain: TagValueDomainCRRF}
}

func (m *crrfAutoPiTRTriggerCase) DeclareDependencyRequirements() map[string]DependencyRequirement {
	return map[string]DependencyRequirement{
		"tidb": &TiDBDedicatedRequirement{
			Dedicated: true,
			TiDBDedicatedDimensions: TiDBDedicatedDimensions{
				CloudProvider: m.cloudProvider,
				Region:        config.GlobalConfig.DefaultRegionOf(m.cloudProvider),
			},
		},
	}
}

func (m *crrfAutoPiTRTriggerCase) Run() {
	tidbCluster := m.TiDBDedicated("tidb")

	m.backupValidator = common.NewBackupValidator(m.Logger())
	m.crrfValidator = common.NewCRRFValidator(m.Logger())

	// CRRF is AWS-only
	if m.cloudProvider != AWS {
		m.Logger().Info("skipping Auto-CRRF PiTR trigger test for non-AWS provider %s", m.cloudProvider)
		return
	}

	var (
		secondaryRegion       string
		originalStateCaptured bool
		createdBackupIDs      []uint64
	)

	// Cleanup: delete backups created during test
	defer func() {
		if !originalStateCaptured {
			return
		}
		m.Logger().Info("cleanup: deleting %d backups created during test", len(createdBackupIDs))
		for _, backupID := range createdBackupIDs {
			if err := m.backupValidator.Client().DeleteBackup(tidbCluster, backupID); err != nil {
				m.Logger().Warn("cleanup: failed to delete backup %d: %v", backupID, err)
			} else {
				m.Logger().Info("cleanup: deleted backup %d", backupID)
			}
		}
		m.Logger().Info("cleanup: completed, cluster will be deleted by test framework")
	}()

	m.Step("capture original backup setting", func() error {
		_, err := m.backupValidator.Client().QueryBackupSetting(tidbCluster)
		if err != nil {
			return err
		}
		originalStateCaptured = true
		return nil
	})

	m.
		Step("enable dual-region backup", func() error {
			var err error
			secondaryRegion, err = m.backupValidator.GetSecondaryRegion(tidbCluster, false)
			if err != nil {
				return err
			}
			return m.backupValidator.EnableDualRegion(tidbCluster, secondaryRegion)
		}).
		Step("wait for dual-region enable to settle", func() error {
			time.Sleep(30 * time.Second)
			return nil
		}).
		Step("wait backup setting ready after dual-region snapshot backup", func() error {
			return m.backupValidator.WaitForBackupSettingReady(tidbCluster, 5*time.Minute)
		}).
		Step("enable PiTR", func() error {
			return m.backupValidator.EnablePiTR(tidbCluster)
		}).
		Step("trigger snapshot backup for CRRF activation", func() error {
			backupID, err := m.backupValidator.TriggerSnapshotBackupAndWait(
				tidbCluster,
				GenerateClusterName("crrf-pitr-trigger"),
				30*time.Minute,
			)
			if err == nil && backupID > 0 {
				createdBackupIDs = append(createdBackupIDs, backupID)
			}
			return err
		}).
		Step("wait backup setting ready after snapshot backup", func() error {
			return m.backupValidator.WaitForBackupSettingReady(tidbCluster, 5*time.Minute)
		}).
		Expect("CRRF auto enabled via PiTR trigger", func() error {
			return m.backupValidator.ExpectCRRFStatus(tidbCluster, "enabled")
		}, 30, 30*time.Second).
		Step("wait backup setting ready before disabling PiTR", func() error {
			return m.backupValidator.WaitForBackupSettingReady(tidbCluster, 5*time.Minute)
		}).
		Step("disable PiTR to auto disable CRRF", func() error {
			return m.backupValidator.DisablePiTR(tidbCluster)
		}).
		Step("wait backup setting ready after PiTR disable", func() error {
			return m.backupValidator.WaitForBackupSettingReady(tidbCluster, 5*time.Minute)
		}).
		Expect("CRRF auto disabled via PiTR disable", func() error {
			return m.backupValidator.ExpectCRRFStatus(tidbCluster, "disabled")
		}, 30, 20*time.Second)
}
