package dockerimg

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

func TestSetupHooksDir(t *testing.T) {
	// Create a temporary git repository
	tmpDir, err := os.MkdirTemp("", "test-git-repo-*")
	if err != nil {
		t.Fatalf("failed to create temp dir: %v", err)
	}
	defer os.RemoveAll(tmpDir)

	// Test setupHooksDir function
	hooksDir, err := setupHooksDir(tmpDir)
	if err != nil {
		t.Fatalf("setupHooksDir failed: %v", err)
	}
	defer os.RemoveAll(hooksDir)

	// Verify hooks directory was created
	if _, err := os.Stat(hooksDir); os.IsNotExist(err) {
		t.Errorf("hooks directory was not created: %s", hooksDir)
	}

	// Verify pre-receive hook was created
	preReceiveHook := filepath.Join(hooksDir, "pre-receive")
	if _, err := os.Stat(preReceiveHook); os.IsNotExist(err) {
		t.Errorf("pre-receive hook was not created: %s", preReceiveHook)
	}

	// Verify pre-receive hook is executable
	info, err := os.Stat(preReceiveHook)
	if err != nil {
		t.Errorf("failed to stat pre-receive hook: %v", err)
	}
	if info.Mode()&0o111 == 0 {
		t.Errorf("pre-receive hook is not executable")
	}

	// Verify pre-receive hook contains expected content
	content, err := os.ReadFile(preReceiveHook)
	if err != nil {
		t.Errorf("failed to read pre-receive hook: %v", err)
	}

	// Check for key elements in the script
	contentStr := string(content)
	if !containsAll(contentStr, []string{
		"#!/bin/bash",
		"refs/remotes/origin/",
		"git push origin",
		"Force pushes are not allowed",
		"git merge-base --is-ancestor",
	}) {
		t.Errorf("pre-receive hook missing expected content")
	}
}

// Helper function to check if a string contains all substrings
func containsAll(str string, substrings []string) bool {
	for _, substr := range substrings {
		if !contains(str, substr) {
			return false
		}
	}
	return true
}

// Helper function to check if a string contains a substring
func contains(str, substr string) bool {
	return len(str) >= len(substr) && findIndex(str, substr) >= 0
}

// Helper function to find index of substring (simple implementation)
func findIndex(str, substr string) int {
	for i := 0; i <= len(str)-len(substr); i++ {
		if str[i:i+len(substr)] == substr {
			return i
		}
	}
	return -1
}

func TestPreReceiveHookScript(t *testing.T) {
	// Create a temporary git repository
	tmpDir, err := os.MkdirTemp("", "test-git-repo-*")
	if err != nil {
		t.Fatalf("failed to create temp dir: %v", err)
	}
	defer os.RemoveAll(tmpDir)

	// Set up hooks directory
	hooksDir, err := setupHooksDir(tmpDir)
	if err != nil {
		t.Fatalf("setupHooksDir failed: %v", err)
	}
	defer os.RemoveAll(hooksDir)

	// Read the pre-receive hook script
	preReceiveHook := filepath.Join(hooksDir, "pre-receive")
	script, err := os.ReadFile(preReceiveHook)
	if err != nil {
		t.Fatalf("failed to read pre-receive hook: %v", err)
	}

	// Verify the script contains the expected bash shebang
	scriptContent := string(script)
	if !contains(scriptContent, "#!/bin/bash") {
		t.Errorf("pre-receive hook missing bash shebang")
	}

	// Verify the script contains logic to handle refs/remotes/origin/Y
	if !contains(scriptContent, "refs/remotes/origin/(.+)") {
		t.Errorf("pre-receive hook missing refs/remotes/origin pattern matching")
	}

	// Verify the script contains force-push protection
	if !contains(scriptContent, "git merge-base --is-ancestor") {
		t.Errorf("pre-receive hook missing force-push protection")
	}

	// Verify the script contains git push origin command
	if !contains(scriptContent, "git push origin") {
		t.Errorf("pre-receive hook missing git push origin command")
	}

	// Verify the script exits with proper error codes
	if !contains(scriptContent, "exit 1") {
		t.Errorf("pre-receive hook missing error exit code")
	}

	if !contains(scriptContent, "exit 0") {
		t.Errorf("pre-receive hook missing success exit code")
	}
}

func TestGitHTTPHooksConfiguration(t *testing.T) {
	// Create a temporary git repository
	tmpDir, err := os.MkdirTemp("", "test-git-repo-*")
	if err != nil {
		t.Fatalf("failed to create temp dir: %v", err)
	}
	defer os.RemoveAll(tmpDir)

	// Initialize git repository
	if err := runGitCommand(tmpDir, "init"); err != nil {
		t.Fatalf("failed to init git repo: %v", err)
	}

	// Set up hooks directory
	hooksDir, err := setupHooksDir(tmpDir)
	if err != nil {
		t.Fatalf("setupHooksDir failed: %v", err)
	}
	defer os.RemoveAll(hooksDir)

	// Create gitHTTP instance
	gitHTTP := &gitHTTP{
		gitRepoRoot: tmpDir,
		hooksDir:    hooksDir,
		pass:        []byte("test-pass"),
		browserC:    make(chan bool, 1),
	}

	// Test that the gitHTTP struct has the hooks directory set
	if gitHTTP.hooksDir == "" {
		t.Errorf("gitHTTP hooksDir is empty")
	}

	if gitHTTP.hooksDir != hooksDir {
		t.Errorf("gitHTTP hooksDir mismatch: expected %s, got %s", hooksDir, gitHTTP.hooksDir)
	}

	// Verify that the hooks directory exists and contains the pre-receive hook
	preReceiveHook := filepath.Join(hooksDir, "pre-receive")
	if _, err := os.Stat(preReceiveHook); os.IsNotExist(err) {
		t.Errorf("pre-receive hook missing: %s", preReceiveHook)
	}
}

// Helper function to run git commands
func runGitCommand(dir string, args ...string) error {
	cmd := exec.Command("git", args...)
	cmd.Dir = dir
	return cmd.Run()
}

func TestPreReceiveHookExecution(t *testing.T) {
	// Create a temporary git repository
	tmpDir, err := os.MkdirTemp("", "test-git-repo-*")
	if err != nil {
		t.Fatalf("failed to create temp dir: %v", err)
	}
	defer os.RemoveAll(tmpDir)

	// Initialize git repository
	if err := runGitCommand(tmpDir, "init"); err != nil {
		t.Fatalf("failed to init git repo: %v", err)
	}

	// Set up hooks directory
	hooksDir, err := setupHooksDir(tmpDir)
	if err != nil {
		t.Fatalf("setupHooksDir failed: %v", err)
	}
	defer os.RemoveAll(hooksDir)

	// Test the hook script syntax by running bash -n on it
	preReceiveHook := filepath.Join(hooksDir, "pre-receive")
	cmd := exec.Command("bash", "-n", preReceiveHook)
	if err := cmd.Run(); err != nil {
		t.Errorf("pre-receive hook has syntax errors: %v", err)
	}

	// Test that the hook script is executable
	info, err := os.Stat(preReceiveHook)
	if err != nil {
		t.Fatalf("failed to stat pre-receive hook: %v", err)
	}

	mode := info.Mode()
	if mode&0o111 == 0 {
		t.Errorf("pre-receive hook is not executable: mode = %v", mode)
	}
}
