package migrate

import (
	"encoding/json"

	dispatchmodel "github.com/tidbcloud/aisupport/services/ticket-manager/models/dispatch"

	"gorm.io/gorm"
)

var _ = addRecord("202607251100", migrateDispatchPolicyTriggerJSON)

func migrateDispatchPolicyTriggerJSON(db *gorm.DB) error {
	if !db.Migrator().HasColumn(&dispatchmodel.Policy{}, "TriggerJSON") {
		if err := db.Migrator().AddColumn(&policyWithNullableTriggerJSON{}, "TriggerJSON"); err != nil {
			return err
		}
	}

	var policyIDs []uint64
	if err := db.Table(dispatchmodel.Policy{}.TableName()).Pluck("id", &policyIDs).Error; err != nil {
		return err
	}
	triggers := make(map[uint64]dispatchmodel.PolicyTrigger, len(policyIDs))
	for _, policyID := range policyIDs {
		triggers[policyID] = dispatchmodel.PolicyTrigger{}
	}

	if db.Migrator().HasTable(&legacyDispatchPolicyTrigger{}) {
		var rows []legacyDispatchPolicyTrigger
		if err := db.Find(&rows).Error; err != nil {
			return err
		}
		for _, row := range rows {
			trigger := triggers[row.PolicyID.Uint64()]
			trigger.Enable = row.Enable
			triggers[row.PolicyID.Uint64()] = trigger
		}
	}
	if db.Migrator().HasTable(&legacyDispatchPolicyTriggerProject{}) {
		var rows []legacyDispatchPolicyTriggerProject
		if err := db.Order("project_key ASC").Find(&rows).Error; err != nil {
			return err
		}
		for _, row := range rows {
			trigger := triggers[row.PolicyID.Uint64()]
			trigger.ProjectKeyIn = append(trigger.ProjectKeyIn, row.ProjectKey)
			triggers[row.PolicyID.Uint64()] = trigger
		}
	}
	if db.Migrator().HasTable(&legacyDispatchPolicyTriggerIssueStatus{}) {
		var rows []legacyDispatchPolicyTriggerIssueStatus
		if err := db.Order("issue_status ASC").Find(&rows).Error; err != nil {
			return err
		}
		for _, row := range rows {
			trigger := triggers[row.PolicyID.Uint64()]
			trigger.IssueStatusIn = append(trigger.IssueStatusIn, row.IssueStatus)
			triggers[row.PolicyID.Uint64()] = trigger
		}
	}

	for _, policyID := range policyIDs {
		triggerJSON, err := json.Marshal(triggers[policyID])
		if err != nil {
			return err
		}
		if err := db.Table(dispatchmodel.Policy{}.TableName()).
			Where("id = ?", policyID).
			Update("trigger_json", triggerJSON).Error; err != nil {
			return err
		}
	}
	if db.Dialector.Name() != "sqlite" {
		if err := db.Migrator().AlterColumn(&dispatchmodel.Policy{}, "TriggerJSON"); err != nil {
			return err
		}
	}

	return db.Migrator().DropTable(
		&legacyDispatchPolicyTriggerIssueStatus{},
		&legacyDispatchPolicyTriggerProject{},
		&legacyDispatchPolicyTrigger{},
	)
}

type policyWithNullableTriggerJSON struct {
	TriggerJSON []byte `gorm:"column:trigger_json;type:json"`
}

func (policyWithNullableTriggerJSON) TableName() string {
	return "dispatch_policies"
}
