package cli

import (
	"testing"

	"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
)

func TestRecomputePolicyIncludesDependentLanesAndReusablePredecessors(t *testing.T) {
	producer := pipeline.ResolvedArtifactLane{StepID: "first", ID: "producer"}
	unrelated := pipeline.ResolvedArtifactLane{StepID: "first", ID: "unrelated"}
	consumer := pipeline.ResolvedArtifactLane{
		StepID: "second", ID: "consumer",
		ExtractReferences: pipeline.ResolvedReferenceTarget{Bindings: []pipeline.ReferenceBinding{{Artifact: &pipeline.ArtifactReference{Step: "first", Lane: "producer"}}}},
	}
	downstream := pipeline.ResolvedArtifactLane{
		StepID: "third", ID: "downstream",
		ExtractReferences: pipeline.ResolvedReferenceTarget{Bindings: []pipeline.ReferenceBinding{{Artifact: &pipeline.ArtifactReference{Step: "second", Lane: "consumer"}}}},
	}
	independent := pipeline.ResolvedArtifactLane{StepID: "third", ID: "independent"}
	resolved := pipeline.ResolvedPipeline{Steps: []pipeline.ResolvedPipelineStep{
		{ID: "first", ArtifactLanes: []pipeline.ResolvedArtifactLane{producer, unrelated}},
		{ID: "second", ArtifactLanes: []pipeline.ResolvedArtifactLane{consumer}},
		{ID: "third", ArtifactLanes: []pipeline.ResolvedArtifactLane{downstream, independent}},
	}}

	policy, err := recomputePolicy(resolved, "second")
	if err != nil {
		t.Fatal(err)
	}
	if _, ok := policy.ForcedLanes[pipeline.CheckpointLaneKey("second", "consumer")]; !ok {
		t.Fatal("selected lane was not forced")
	}
	if _, ok := policy.ForcedLanes[pipeline.CheckpointLaneKey("third", "downstream")]; !ok {
		t.Fatal("transitive dependent lane was not forced")
	}
	if _, ok := policy.ForcedLanes[pipeline.CheckpointLaneKey("first", "producer")]; ok {
		t.Fatal("predecessor was implicitly forced")
	}
	if _, ok := policy.RequireReusableLanes[pipeline.CheckpointLaneKey("first", "producer")]; !ok {
		t.Fatal("required predecessor was not marked reusable")
	}
	if _, ok := policy.ForcedLanes[pipeline.CheckpointLaneKey("first", "unrelated")]; ok {
		t.Fatal("unrelated lane was forced")
	}
	if _, ok := policy.ForcedLanes[pipeline.CheckpointLaneKey("third", "independent")]; ok {
		t.Fatal("unrelated later lane was forced")
	}
}

func TestRecomputePolicyRejectsUnknownStep(t *testing.T) {
	_, err := recomputePolicy(pipeline.ResolvedPipeline{Steps: []pipeline.ResolvedPipelineStep{{ID: "known"}}}, "missing")
	if err == nil {
		t.Fatal("unknown step was accepted")
	}
}
