package sdlc

import (
	"os"
	"path/filepath"
	"testing"
)

func setupTestSDLC(t *testing.T) string {
	t.Helper()
	root := t.TempDir()
	if err := Init(root, "test-project"); err != nil {
		t.Fatalf("init failed: %v", err)
	}
	return root
}

func TestCreateBranch(t *testing.T) {
	root := setupTestSDLC(t)
	cfg := DefaultConfig("test")

	// Create a feature and transition to planned phase (branch creation requires planned or later)
	f, err := CreateFeature(root, "auth-flow", "Auth Flow")
	if err != nil {
		t.Fatalf("create feature: %v", err)
	}
	f.Phase = PhasePlanned
	if err := f.Save(root); err != nil {
		t.Fatalf("save feature: %v", err)
	}

	manifest, err := CreateBranch(root, "auth-flow", cfg)
	if err != nil {
		t.Fatalf("create branch: %v", err)
	}

	if manifest.Name != "feature/auth-flow" {
		t.Errorf("Name = %q, want feature/auth-flow", manifest.Name)
	}
	if manifest.Feature != "auth-flow" {
		t.Errorf("Feature = %q, want auth-flow", manifest.Feature)
	}
	if manifest.BaseBranch != "main" {
		t.Errorf("BaseBranch = %q, want main", manifest.BaseBranch)
	}

	// Verify feature was updated with branch reference
	f, err = LoadFeature(root, "auth-flow")
	if err != nil {
		t.Fatalf("load feature: %v", err)
	}
	if f.Branch != "feature/auth-flow" {
		t.Errorf("Feature.Branch = %q, want feature/auth-flow", f.Branch)
	}
}

func TestCreateBranch_AlreadyExists(t *testing.T) {
	root := setupTestSDLC(t)
	cfg := DefaultConfig("test")

	f, err := CreateFeature(root, "auth-flow", "Auth Flow")
	if err != nil {
		t.Fatalf("create feature: %v", err)
	}
	f.Phase = PhasePlanned
	if err := f.Save(root); err != nil {
		t.Fatalf("save feature: %v", err)
	}

	if _, err := CreateBranch(root, "auth-flow", cfg); err != nil {
		t.Fatalf("create branch: %v", err)
	}

	_, err = CreateBranch(root, "auth-flow", cfg)
	if err != ErrBranchExists {
		t.Errorf("err = %v, want ErrBranchExists", err)
	}
}

func TestCreateBranch_FeatureNotFound(t *testing.T) {
	root := setupTestSDLC(t)
	cfg := DefaultConfig("test")

	_, err := CreateBranch(root, "nonexistent", cfg)
	if err != ErrFeatureNotFound {
		t.Errorf("err = %v, want ErrFeatureNotFound", err)
	}
}

func TestLoadBranch(t *testing.T) {
	root := setupTestSDLC(t)
	cfg := DefaultConfig("test")

	f, err := CreateFeature(root, "auth-flow", "Auth Flow")
	if err != nil {
		t.Fatalf("create feature: %v", err)
	}
	f.Phase = PhasePlanned
	if err := f.Save(root); err != nil {
		t.Fatalf("save feature: %v", err)
	}

	_, err = CreateBranch(root, "auth-flow", cfg)
	if err != nil {
		t.Fatalf("create branch: %v", err)
	}

	manifest, err := LoadBranch(root, "feature/auth-flow")
	if err != nil {
		t.Fatalf("load branch: %v", err)
	}
	if manifest.Name != "feature/auth-flow" {
		t.Errorf("Name = %q, want feature/auth-flow", manifest.Name)
	}
}

func TestLoadBranch_NotFound(t *testing.T) {
	root := setupTestSDLC(t)

	_, err := LoadBranch(root, "nonexistent")
	if err != ErrBranchNotFound {
		t.Errorf("err = %v, want ErrBranchNotFound", err)
	}
}

func TestSaveBranch(t *testing.T) {
	root := setupTestSDLC(t)

	manifest := &BranchManifest{
		Name:       "feature/test",
		Feature:    "test",
		BaseBranch: "main",
	}

	if err := SaveBranch(root, manifest); err != nil {
		t.Fatalf("save branch: %v", err)
	}

	// Verify file exists
	path := filepath.Join(root, SDLCDir, BranchesDir, "feature/test.yaml")
	if _, err := os.Stat(path); os.IsNotExist(err) {
		t.Error("branch manifest file not created")
	}
}

func TestMergeChecklist_NotReady(t *testing.T) {
	root := setupTestSDLC(t)

	_, err := CreateFeature(root, "auth-flow", "Auth Flow")
	if err != nil {
		t.Fatalf("create feature: %v", err)
	}

	unmet, err := MergeChecklist(root, "auth-flow")
	if err != nil {
		t.Fatalf("merge checklist: %v", err)
	}

	if len(unmet) == 0 {
		t.Error("expected unmet gates, got none")
	}
}

func TestMergeChecklist_Ready(t *testing.T) {
	root := setupTestSDLC(t)

	f, err := CreateFeature(root, "auth-flow", "Auth Flow")
	if err != nil {
		t.Fatalf("create feature: %v", err)
	}

	// Set up all gates as passed and transition to merge phase
	f.Phase = PhaseMerge
	f.GetArtifact(ArtifactReview).MarkPassed()
	f.GetArtifact(ArtifactAudit).MarkPassed()
	f.GetArtifact(ArtifactQAResults).MarkPassed()
	if err := f.Save(root); err != nil {
		t.Fatalf("save feature: %v", err)
	}

	unmet, err := MergeChecklist(root, "auth-flow")
	if err != nil {
		t.Fatalf("merge checklist: %v", err)
	}

	if len(unmet) != 0 {
		t.Errorf("expected 0 unmet gates, got %d: %v", len(unmet), unmet)
	}
}

func TestMergeChecklist_FeatureNotFound(t *testing.T) {
	root := setupTestSDLC(t)

	_, err := MergeChecklist(root, "nonexistent")
	if err != ErrFeatureNotFound {
		t.Errorf("err = %v, want ErrFeatureNotFound", err)
	}
}
