package k8supgrade

import (
	"reflect"
	"strings"
	"testing"

	regionalpb "github.com/tidbcloud/infra-provider/api/tidbcloud/regional-server/v1"

	"github.com/tidbcloud/infra-provider/regional-server/api/v1alpha1"
)

func TestMergeAnnotations(t *testing.T) {
	existing := map[string]string{
		"maintenance.pingcap.com/request-step-1": `{"spec":{"cluster_id":"1"}}`,
		"keep":                                   "value",
	}
	existingCopy := map[string]string{
		"maintenance.pingcap.com/request-step-1": `{"spec":{"cluster_id":"1"}}`,
		"keep":                                   "value",
	}
	desired := map[string]string{
		"maintenance.pingcap.com/request-step-1": `{"spec":{"cluster_id":"1"},"status":{"result":"done"}}`,
	}
	got := mergeAnnotations(existing, desired)
	want := map[string]string{
		"maintenance.pingcap.com/request-step-1": `{"spec":{"cluster_id":"1"},"status":{"result":"done"}}`,
		"keep":                                   "value",
	}
	if !reflect.DeepEqual(got, want) {
		t.Fatalf("mergeAnnotations() = %#v, want %#v", got, want)
	}
	if !reflect.DeepEqual(existing, existingCopy) {
		t.Fatalf("mergeAnnotations() mutated existing map: got %#v, want %#v", existing, existingCopy)
	}
}

func TestCloneStringMapNil(t *testing.T) {
	if cloneStringMap(nil) != nil {
		t.Fatal("expected nil map")
	}
}

func TestPbUpgradeOperation2UpgradeOperationMaintenancePolicyMode(t *testing.T) {
	base := &regionalpb.UpgradeOperation{
		Name:       "uo-1",
		AppboxName: "appbox-1",
		Schedule:   "2026-01-01 00:00:00 +0000 UTC",
		Duration:   "2h",
		Ttl:        "8760h",
	}

	t.Run("empty defaults to legacy", func(t *testing.T) {
		uo, err := pbUpgradeOperation2UpgradeOperation(base)
		if err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if uo.Spec.MaintenancePolicyMode != v1alpha1.MaintenancePolicyModeLegacy {
			t.Fatalf("got %q, want %q", uo.Spec.MaintenancePolicyMode, v1alpha1.MaintenancePolicyModeLegacy)
		}
	})

	t.Run("cluster-maintenance accepted", func(t *testing.T) {
		req := *base
		req.MaintenancePolicyMode = v1alpha1.MaintenancePolicyModeClusterMaintenance
		uo, err := pbUpgradeOperation2UpgradeOperation(&req)
		if err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if uo.Spec.MaintenancePolicyMode != v1alpha1.MaintenancePolicyModeClusterMaintenance {
			t.Fatalf("got %q, want %q", uo.Spec.MaintenancePolicyMode, v1alpha1.MaintenancePolicyModeClusterMaintenance)
		}
	})

	t.Run("typo rejected", func(t *testing.T) {
		req := *base
		req.MaintenancePolicyMode = "cluster-maintenace"
		_, err := pbUpgradeOperation2UpgradeOperation(&req)
		if err == nil {
			t.Fatal("expected error for invalid maintenance_policy_mode")
		}
		if !strings.Contains(err.Error(), "invalid maintenance_policy_mode") {
			t.Fatalf("unexpected error: %v", err)
		}
	})
}
