package phase

import (
	"testing"

	"github.com/tidbcloud/devops/entity"
	"github.com/tidbcloud/devops/pkg/infra/config"
)

func TestValidateWorkflowDefinition(t *testing.T) {
	empty := config.RemediationWorkflowDefinitionConfig{}
	if err := validateWorkflowDefinition(empty); err != nil {
		t.Fatalf("expected empty workflow config to use defaults, got error: %v", err)
	}

	valid := config.RemediationWorkflowDefinitionConfig{
		Phases: []string{
			entity.RemediationTicketPhaseCreated,
			entity.RemediationTicketPhaseRegionTSELeader,
			entity.RemediationTicketPhaseRDGSLAOwner,
			entity.RemediationTicketPhaseGlobalDealDesk,
			entity.RemediationTicketPhaseRDGFinalDecisionMaker,
			entity.RemediationTicketPhaseRegionalGM,
			entity.RemediationTicketPhaseSucceed,
			entity.RemediationTicketPhaseClosed,
		},
		Labels: map[string]string{
			entity.RemediationTicketPhaseRDGSLAOwner: "EG SLA Owner",
		},
	}
	if err := validateWorkflowDefinition(valid); err != nil {
		t.Fatalf("expected valid config, got error: %v", err)
	}
}

func TestValidateWorkflowDefinitionInvalid(t *testing.T) {
	cases := []struct {
		name   string
		config config.RemediationWorkflowDefinitionConfig
	}{
		{
			name: "unknown phase in phase list",
			config: config.RemediationWorkflowDefinitionConfig{
				Phases: []string{"created", "unknown_phase", "succeed", "closed"},
			},
		},
		{
			name: "duplicate phase in phase list",
			config: config.RemediationWorkflowDefinitionConfig{
				Phases: []string{"created", "region_tse_leader", "region_tse_leader", "succeed", "closed"},
			},
		},
		{
			name: "must start with created",
			config: config.RemediationWorkflowDefinitionConfig{
				Phases: []string{"region_tse_leader", "succeed", "closed"},
			},
		},
		{
			name: "must include succeed",
			config: config.RemediationWorkflowDefinitionConfig{
				Phases: []string{"created", "region_tse_leader", "closed"},
			},
		},
		{
			name: "must include closed",
			config: config.RemediationWorkflowDefinitionConfig{
				Phases: []string{"created", "region_tse_leader", "succeed"},
			},
		},
		{
			name: "must end with succeed and closed",
			config: config.RemediationWorkflowDefinitionConfig{
				Phases: []string{"created", "region_tse_leader", "closed", "succeed"},
			},
		},
		{
			name: "optional phase must exist in phases",
			config: config.RemediationWorkflowDefinitionConfig{
				Phases:         []string{"created", "region_tse_leader", "succeed", "closed"},
				OptionalPhases: []string{"commercial_operation"},
			},
		},
		{
			name: "label key must be valid phase",
			config: config.RemediationWorkflowDefinitionConfig{
				Phases: []string{"created", "region_tse_leader", "succeed", "closed"},
				Labels: map[string]string{"unknown_phase": "Unknown"},
			},
		},
	}

	for _, tc := range cases {
		if err := validateWorkflowDefinition(tc.config); err == nil {
			t.Fatalf("%s: expected validation error, got nil", tc.name)
		}
	}
}

func TestMetadataUsesPhaseHandlerDefaults(t *testing.T) {
	t.Cleanup(func() {
		if err := ConfigureWorkflow(config.RemediationWorkflowConfig{}); err != nil {
			t.Fatalf("reset workflow config failed: %v", err)
		}
	})

	if err := ConfigureWorkflow(config.RemediationWorkflowConfig{}); err != nil {
		t.Fatalf("ConfigureWorkflow returned error: %v", err)
	}

	created := Metadata(entity.RemediationTicketPhaseCreated)
	if created.IsFinalized {
		t.Fatalf("created phase should not be finalized")
	}

	regionTSELeader := Metadata(entity.RemediationTicketPhaseRegionTSELeader)
	if !regionTSELeader.RequiresInput {
		t.Fatalf("region_tse_leader should require input")
	}
	if regionTSELeader.AutoAdvance {
		t.Fatalf("region_tse_leader should not auto advance")
	}

	rdgFinalDecisionMaker := Metadata(entity.RemediationTicketPhaseRDGFinalDecisionMaker)
	if rdgFinalDecisionMaker.RequiresInput {
		t.Fatalf("rdg_final_decision_maker should not require input")
	}
	if !rdgFinalDecisionMaker.AutoAdvance {
		t.Fatalf("rdg_final_decision_maker should auto advance")
	}
}

func TestResolveNextPhaseWithGlobalDealDeskBeforeRDGFinalDecisionMaker(t *testing.T) {
	t.Cleanup(func() {
		if err := ConfigureWorkflow(config.RemediationWorkflowConfig{}); err != nil {
			t.Fatalf("reset workflow config failed: %v", err)
		}
	})

	err := ConfigureWorkflow(config.RemediationWorkflowConfig{
		Default: config.RemediationWorkflowDefinitionConfig{
			Phases: []string{
				entity.RemediationTicketPhaseCreated,
				entity.RemediationTicketPhaseRegionTSELeader,
				entity.RemediationTicketPhaseRDGSLAOwner,
				entity.RemediationTicketPhaseGlobalDealDesk,
				entity.RemediationTicketPhaseRDGFinalDecisionMaker,
				entity.RemediationTicketPhaseCommercialOperation,
				entity.RemediationTicketPhaseRegionalGM,
				entity.RemediationTicketPhaseSucceed,
				entity.RemediationTicketPhaseClosed,
			},
			OptionalPhases: []string{
				entity.RemediationTicketPhaseCommercialOperation,
			},
		},
	})
	if err != nil {
		t.Fatalf("ConfigureWorkflow returned error: %v", err)
	}

	next, err := ResolveNextPhase(entity.RemediationTicketPhaseGlobalDealDesk, &entity.RemediationTicket{
		ExtraPercent: "0",
	})
	if err != nil {
		t.Fatalf("ResolveNextPhase(global_deal_desk) returned error: %v", err)
	}
	if next != entity.RemediationTicketPhaseRDGFinalDecisionMaker {
		t.Fatalf("ResolveNextPhase(global_deal_desk) = %s, want %s", next, entity.RemediationTicketPhaseRDGFinalDecisionMaker)
	}

	next, err = ResolveNextPhase(entity.RemediationTicketPhaseRDGFinalDecisionMaker, &entity.RemediationTicket{
		ExtraPercent: "0",
	})
	if err != nil {
		t.Fatalf("ResolveNextPhase(rdg_final_decision_maker, extra 0) returned error: %v", err)
	}
	if next != entity.RemediationTicketPhaseRegionalGM {
		t.Fatalf("ResolveNextPhase(rdg_final_decision_maker, extra 0) = %s, want %s", next, entity.RemediationTicketPhaseRegionalGM)
	}

	next, err = ResolveNextPhase(entity.RemediationTicketPhaseRDGFinalDecisionMaker, &entity.RemediationTicket{
		ExtraPercent: "5",
	})
	if err != nil {
		t.Fatalf("ResolveNextPhase(rdg_final_decision_maker, extra 5) returned error: %v", err)
	}
	if next != entity.RemediationTicketPhaseCommercialOperation {
		t.Fatalf("ResolveNextPhase(rdg_final_decision_maker, extra 5) = %s, want %s", next, entity.RemediationTicketPhaseCommercialOperation)
	}
}
