package projectsync

import (
	"errors"
	"testing"
)

func validCheckoutConfig() Config {
	return Config{
		Target: ProviderProjectTarget{
			Provider: "plane",
			Tenant:   "general",
			Project:  "project-1",
		},
		GitRemoteURL:      "git@example.com:org/nomadcode.git",
		SourceBranch:      "develop",
		WorkspaceID:       "ws-main",
		WorkspaceBasePath: "/home/user/workspace",
		RepoDirName:       "nomadcode",
	}
}

func TestBuildProvisionPlanIncludesBranchAndDefaultSlotPaths(t *testing.T) {
	plan, err := BuildProvisionPlan(validCheckoutConfig())
	if err != nil {
		t.Fatalf("BuildProvisionPlan returned error: %v", err)
	}
	if plan.ProjectWorkspaceRoot != "/home/user/workspace/nomadcode" {
		t.Errorf("project root: got %q", plan.ProjectWorkspaceRoot)
	}
	if plan.MainBranchPath != "/home/user/workspace/nomadcode/branches/main" {
		t.Errorf("main branch path: got %q", plan.MainBranchPath)
	}
	if plan.DevelopBranchPath != "/home/user/workspace/nomadcode/branches/develop" {
		t.Errorf("develop branch path: got %q", plan.DevelopBranchPath)
	}
	if plan.DefaultSlotPath != "/home/user/workspace/nomadcode/slots/000" {
		t.Errorf("default slot path: got %q", plan.DefaultSlotPath)
	}
	// Branch paths and slot path must be distinct.
	if plan.MainBranchPath == plan.DefaultSlotPath || plan.DevelopBranchPath == plan.DefaultSlotPath {
		t.Error("branch paths and slot path must not collide")
	}
	if plan.MainBranchPath == plan.DevelopBranchPath {
		t.Error("main and develop branch paths must be distinct")
	}
}

func TestBuildProvisionPlanRejectsInvalidConfig(t *testing.T) {
	bad := validCheckoutConfig()
	bad.GitRemoteURL = ""
	if _, err := BuildProvisionPlan(bad); !errors.Is(err, ErrInvalidConfig) {
		t.Fatalf("expected ErrInvalidConfig, got %v", err)
	}
}

func TestBuildCheckoutPlanDefaultSlotUsesZeroPaddedPath(t *testing.T) {
	plan, err := BuildCheckoutPlan(validCheckoutConfig(), WorkspaceSlot{Index: DefaultSlotIndex})
	if err != nil {
		t.Fatalf("BuildCheckoutPlan returned error: %v", err)
	}
	if plan.RemoteURL != "git@example.com:org/nomadcode.git" {
		t.Errorf("remote: got %q", plan.RemoteURL)
	}
	if plan.SourceBranch != "develop" {
		t.Errorf("source branch: got %q", plan.SourceBranch)
	}
	if plan.ProjectWorkspaceRoot != "/home/user/workspace/nomadcode" {
		t.Errorf("project root: got %q", plan.ProjectWorkspaceRoot)
	}
	if plan.SlotPath != "/home/user/workspace/nomadcode/slots/000" {
		t.Errorf("slot path: got %q", plan.SlotPath)
	}
	if plan.SlotIndex != DefaultSlotIndex {
		t.Errorf("slot index: got %d", plan.SlotIndex)
	}
}

func TestBuildCheckoutPlanParallelSlotKeepsRemoteAndIncrementsPath(t *testing.T) {
	plan, err := BuildCheckoutPlan(validCheckoutConfig(), WorkspaceSlot{Index: SlotIndex(1)})
	if err != nil {
		t.Fatalf("BuildCheckoutPlan returned error: %v", err)
	}
	// Parallel slot keeps the same remote/branch but gets an independent path.
	if plan.RemoteURL != "git@example.com:org/nomadcode.git" {
		t.Errorf("remote: got %q", plan.RemoteURL)
	}
	if plan.SourceBranch != "develop" {
		t.Errorf("source branch: got %q", plan.SourceBranch)
	}
	if plan.SlotPath != "/home/user/workspace/nomadcode/slots/001" {
		t.Errorf("slot path: got %q", plan.SlotPath)
	}
}

func TestBuildCheckoutPlanRejectsInvalidConfig(t *testing.T) {
	bad := validCheckoutConfig()
	bad.GitRemoteURL = ""
	if _, err := BuildCheckoutPlan(bad, WorkspaceSlot{Index: DefaultSlotIndex}); !errors.Is(err, ErrInvalidConfig) {
		t.Fatalf("expected ErrInvalidConfig, got %v", err)
	}
}

func TestBuildCheckoutPlanRejectsInvalidSlotIndex(t *testing.T) {
	for _, index := range []SlotIndex{-1, MaxSlotIndex + 1} {
		if _, err := BuildCheckoutPlan(validCheckoutConfig(), WorkspaceSlot{Index: index}); !errors.Is(err, ErrInvalidConfig) {
			t.Errorf("index %d: expected ErrInvalidConfig, got %v", index, err)
		}
	}
}
