package dm

import (
	"fmt"
	"time"

	. "github.com/tidbcloud/dataflow-service-e2e/cases"
	"github.com/tidbcloud/dataflow-service-e2e/cases/premium/common"
	"github.com/tidbcloud/dataflow-service-e2e/internal/config"
	. "github.com/tidbcloud/dataflow-service-e2e/internal/model"
	dm_model "github.com/tidbcloud/dataflow-service-e2e/internal/tidbcloud/premium/consoleapi/dm/model"
)

// dmPrecheckSmokeCase tests premium DM precheck functionality.
// It creates a precheck request, polls until done, then verifies precheck results.
type dmPrecheckSmokeCase struct {
	BaseCase
	dmValidator   *common.PremiumDMValidator
	cloudProvider CloudProviderType
}

// NewDMPrecheckSmokeCase creates a new precheck smoke test case.
func NewDMPrecheckSmokeCase(cloudProvider CloudProviderType) E2ECase {
	return &dmPrecheckSmokeCase{cloudProvider: cloudProvider}
}

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

func (m *dmPrecheckSmokeCase) Tags() map[string]string {
	return map[string]string{TagKeyDomain: TagValueDomainDM}
}

func (m *dmPrecheckSmokeCase) DeclareDependencyRequirements() map[string]DependencyRequirement {
	return map[string]DependencyRequirement{
		"premium": &TiDBPremiumRequirement{
			Dedicated: false,
			TiDBPremiumDimensions: TiDBPremiumDimensions{
				CloudProvider: m.cloudProvider,
				Region:        config.GlobalConfig.DefaultRegionOf(m.cloudProvider),
			},
		},
		"mysql": &MySQLRequirement{
			MySQLDimensions: MySQLDimensions{
				NetworkType: DataflowNetworkTypeNetworkTypePublic,
			},
		},
	}
}

func (m *dmPrecheckSmokeCase) Run() {
	tidbCluster := m.TiDBPremium("premium")
	mysql := m.MySQL("mysql")
	m.dmValidator = common.NewPremiumDMValidator(m.Logger())

	var precheckID string

	// Cleanup: cancel precheck if still running
	defer func() {
		if precheckID != "" {
			m.RetryDo(fmt.Sprintf("cleanup: cancel precheck %s", precheckID), func() error {
				return m.dmValidator.Client().CancelPrecheck(tidbCluster, precheckID)
			}, DefaultRetryAttempts, DefaultRetryInterval)
		}
	}()

	m.
		// Step 1: Submit a precheck request
		Step("submit premium DM precheck", func() error {
			body := BuildPrecheckBody(
				GenerateMigrationName("precheck"),
				dm_model.V1beta2PremiumDMTaskModeALL,
				dm_model.PremiumDMTaskImportModeENUMIMPORTMODELOGICAL,
				tidbCluster, mysql,
				DefaultDBForDMTest,
			)
			id, err := m.dmValidator.Client().CreatePrecheck(tidbCluster, body)
			if err != nil {
				return err
			}
			precheckID = id
			m.Logger().Info("precheck submitted: %s", precheckID)
			return nil
		}).

		// Step 2: Wait for precheck to complete
		Expect("precheck is done", func() error {
			return m.dmValidator.IsPrecheckDone(tidbCluster, precheckID)
		}, uint(PrecheckTimeout/(30*time.Second)), 30*time.Second).

		// Step 3: Verify precheck result contains items
		Step("verify precheck result", func() error {
			resp, err := m.dmValidator.Client().GetPrecheck(tidbCluster, precheckID)
			if err != nil {
				return err
			}
			if len(resp.Items) == 0 {
				return fmt.Errorf("precheck returned no items")
			}
			m.Logger().Info("precheck returned %d items, total=%d, success=%d, failed=%d, warn=%d",
				len(resp.Items), resp.Total, resp.SuccessCnt, resp.FailedCnt, resp.WarnCnt)
			return nil
		})

	precheckID = ""
}
