package db

import (
	"fmt"

	"gorm.io/gorm"
)

// MigrateRepositorySyncEndpointClaims converts the original one-to-one
// endpoint reservation into the current source-fan-out model. An active
// Binding reserves only its target endpoint; its source may back up or seed
// more than one repository. Existing pair history remains untouched.
func MigrateRepositorySyncEndpointClaims(database *gorm.DB) error {
	if !database.Migrator().HasTable("sync_bindings") || !database.Migrator().HasTable("sync_binding_endpoints") {
		return nil
	}
	return database.Transaction(func(tx *gorm.DB) error {
		var bindings []SyncBinding
		if err := tx.Where("status = ?", "active").Find(&bindings).Error; err != nil {
			return err
		}
		for _, binding := range bindings {
			targetSide := "a"
			switch binding.AuthoritySide {
			case "a":
				targetSide = "b"
			case "b":
				targetSide = "a"
			default:
				return fmt.Errorf("repository sync binding %d has invalid authority side %q", binding.ID, binding.AuthoritySide)
			}
			var endpoints []SyncBindingEndpoint
			if err := tx.Where("binding_id = ?", binding.ID).Find(&endpoints).Error; err != nil {
				return err
			}
			for _, endpoint := range endpoints {
				var claim *string
				if endpoint.Side == targetSide {
					value := endpoint.Provider + ":" + endpoint.RepositoryID
					claim = &value
				}
				if err := tx.Model(&SyncBindingEndpoint{}).
					Where("binding_id = ? AND side = ?", endpoint.BindingID, endpoint.Side).
					Update("active_claim_key", claim).Error; err != nil {
					return err
				}
			}
		}
		return nil
	})
}
