package main

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

func TestMirrorGitRepositoryCopiesRefsWithoutEmbeddingTokens(t *testing.T) {
	ctx := context.Background()
	root := t.TempDir()
	source := filepath.Join(root, "source.git")
	target := filepath.Join(root, "target.git")
	work := filepath.Join(root, "work")
	if err := runGit(ctx, "", "init", "--bare", source); err != nil {
		t.Fatalf("initialize source: %v", err)
	}
	if err := runGit(ctx, "", "init", "--bare", target); err != nil {
		t.Fatalf("initialize target: %v", err)
	}
	if err := runGit(ctx, "", "init", work); err != nil {
		t.Fatalf("initialize work tree: %v", err)
	}
	for _, args := range [][]string{{"config", "user.name", "Migration Test"}, {"config", "user.email", "migration@example.test"}} {
		if err := runGit(ctx, work, args...); err != nil {
			t.Fatalf("configure work tree: %v", err)
		}
	}
	if err := os.WriteFile(filepath.Join(work, "README.md"), []byte("imported\n"), 0o600); err != nil {
		t.Fatalf("write source file: %v", err)
	}
	for _, args := range [][]string{{"add", "README.md"}, {"commit", "-m", "initial"}, {"branch", "-M", "main"}, {"remote", "add", "origin", source}, {"push", "origin", "main"}, {"tag", "v1.0.0"}, {"push", "origin", "v1.0.0"}} {
		if err := runGit(ctx, work, args...); err != nil {
			t.Fatalf("prepare source repository: %v", err)
		}
	}

	if err := mirrorGitRepository(ctx, source, "source-token", target, "target-token", root); err != nil {
		t.Fatalf("mirror repository: %v", err)
	}
	if err := runGit(ctx, "", "--git-dir="+target, "show-ref", "--verify", "refs/heads/main"); err != nil {
		t.Fatalf("target main ref: %v", err)
	}
	if err := runGit(ctx, "", "--git-dir="+target, "show-ref", "--verify", "refs/tags/v1.0.0"); err != nil {
		t.Fatalf("target tag ref: %v", err)
	}
}

func TestMirrorGitRepositorySupportsRelativeWorkDir(t *testing.T) {
	ctx := context.Background()
	root := t.TempDir()
	source := filepath.Join(root, "source.git")
	target := filepath.Join(root, "target.git")
	work := filepath.Join(root, "work")
	if err := runGit(ctx, "", "init", "--bare", source); err != nil {
		t.Fatalf("initialize source: %v", err)
	}
	if err := runGit(ctx, "", "init", "--bare", target); err != nil {
		t.Fatalf("initialize target: %v", err)
	}
	if err := runGit(ctx, "", "init", work); err != nil {
		t.Fatalf("initialize work tree: %v", err)
	}
	for _, args := range [][]string{{"config", "user.name", "Migration Test"}, {"config", "user.email", "migration@example.test"}} {
		if err := runGit(ctx, work, args...); err != nil {
			t.Fatalf("configure work tree: %v", err)
		}
	}
	if err := os.WriteFile(filepath.Join(work, "README.md"), []byte("imported\n"), 0o600); err != nil {
		t.Fatalf("write source file: %v", err)
	}
	for _, args := range [][]string{{"add", "README.md"}, {"commit", "-m", "initial"}, {"branch", "-M", "main"}, {"remote", "add", "origin", source}, {"push", "origin", "main"}} {
		if err := runGit(ctx, work, args...); err != nil {
			t.Fatalf("prepare source repository: %v", err)
		}
	}

	wd, err := os.Getwd()
	if err != nil {
		t.Fatalf("get working directory: %v", err)
	}
	relativeRoot, err := filepath.Rel(wd, root)
	if err != nil {
		t.Fatalf("build relative work directory: %v", err)
	}
	if filepath.IsAbs(relativeRoot) {
		t.Fatalf("expected a relative work directory, got %q", relativeRoot)
	}
	if err := mirrorGitRepository(ctx, source, "source-token", target, "target-token", relativeRoot); err != nil {
		t.Fatalf("mirror repository from relative work directory: %v", err)
	}
	if err := runGit(ctx, "", "--git-dir="+target, "show-ref", "--verify", "refs/heads/main"); err != nil {
		t.Fatalf("target main ref: %v", err)
	}
}

func TestGitRemoteForAPIBaseAndAuthorizationHeader(t *testing.T) {
	githubRemote, err := githubGitRemote("https://api.github.com", "pingcap", "agent-git-service")
	if err != nil {
		t.Fatalf("github remote: %v", err)
	}
	if githubRemote != "https://github.com/pingcap/agent-git-service.git" {
		t.Fatalf("github remote = %q", githubRemote)
	}
	agsRemote, err := agsGitRemote("https://git.staging.agent-git.dev/api/v3", "clawmem", "repo")
	if err != nil {
		t.Fatalf("AGS remote: %v", err)
	}
	if agsRemote != "https://git.staging.agent-git.dev/clawmem/repo.git" {
		t.Fatalf("AGS remote = %q", agsRemote)
	}
	config := strings.Join(gitHTTPAuthorizationConfig("secret-token"), "\n")
	if strings.Contains(config, "https://") || strings.Contains(config, "secret-token@") {
		t.Fatalf("token auth config must not embed credentials in a remote URL: %q", config)
	}
}
