package gitstore

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

	"github.com/pingcap/agent-git-service/internal/tenant"
)

func TestNewForTenantClaimsAndVerifiesRoot(t *testing.T) {
	root := t.TempDir()
	store, err := NewForTenant(root, tenant.ID("clawmem"))
	if err != nil {
		t.Fatalf("NewForTenant first claim: %v", err)
	}
	if store.CanonicalRoot() == "" {
		t.Fatal("CanonicalRoot is empty")
	}

	marker, err := os.ReadFile(filepath.Join(root, tenantRootMarker))
	if err != nil {
		t.Fatalf("read marker: %v", err)
	}
	if got := strings.TrimSpace(string(marker)); got != "clawmem" {
		t.Fatalf("marker = %q, want clawmem", got)
	}
	if _, err := NewForTenant(root, tenant.ID("clawmem")); err != nil {
		t.Fatalf("NewForTenant same tenant: %v", err)
	}
}

func TestNewForTenantRejectsRootOwnedByAnotherTenant(t *testing.T) {
	root := t.TempDir()
	if _, err := NewForTenant(root, tenant.ID("clawmem")); err != nil {
		t.Fatalf("claim clawmem: %v", err)
	}
	if _, err := NewForTenant(root, tenant.ID("engineering")); err == nil {
		t.Fatal("expected ownership mismatch")
	}
}

func TestNewForTenantCanonicalizesSymlinkRoot(t *testing.T) {
	realRoot := t.TempDir()
	linkParent := t.TempDir()
	link := filepath.Join(linkParent, "repos")
	if err := os.Symlink(realRoot, link); err != nil {
		t.Fatalf("symlink: %v", err)
	}
	store, err := NewForTenant(link, tenant.ID("engineering"))
	if err != nil {
		t.Fatalf("NewForTenant: %v", err)
	}
	want, err := filepath.EvalSymlinks(realRoot)
	if err != nil {
		t.Fatalf("EvalSymlinks: %v", err)
	}
	if store.CanonicalRoot() != want {
		t.Fatalf("CanonicalRoot = %q, want %q", store.CanonicalRoot(), want)
	}
}

func TestVerifyTenantRootDetectsMissingOrReassignedMarker(t *testing.T) {
	root := t.TempDir()
	store, err := NewForTenant(root, tenant.ID("tenant-a"))
	if err != nil {
		t.Fatalf("NewForTenant: %v", err)
	}
	if err := store.VerifyTenantRoot("tenant-a"); err != nil {
		t.Fatalf("VerifyTenantRoot: %v", err)
	}

	marker := filepath.Join(store.CanonicalRoot(), tenantRootMarker)
	if err := os.WriteFile(marker, []byte("tenant-b\n"), 0o640); err != nil {
		t.Fatalf("rewrite marker: %v", err)
	}
	if err := store.VerifyTenantRoot("tenant-a"); err == nil {
		t.Fatal("VerifyTenantRoot accepted a marker owned by another tenant")
	}
}

func TestNewForTenantClaimsConfiguredLegacyRoot(t *testing.T) {
	root := t.TempDir()
	if err := os.WriteFile(filepath.Join(root, "existing-repo.git"), []byte("legacy"), 0o640); err != nil {
		t.Fatalf("seed legacy root: %v", err)
	}

	store, err := NewForTenant(root, "tenant-a")
	if err != nil {
		t.Fatalf("claim configured legacy root: %v", err)
	}
	if err := store.VerifyTenantRoot("tenant-a"); err != nil {
		t.Fatalf("VerifyTenantRoot after claim: %v", err)
	}
	if got, err := os.ReadFile(filepath.Join(root, "existing-repo.git")); err != nil || string(got) != "legacy" {
		t.Fatalf("legacy root contents changed: data=%q err=%v", got, err)
	}
}
