Refactor everything

Change-Id: Ic3a37c38cfecba943c91f6ae545ce1c5b551c0d5
diff --git a/server/git/git.go b/server/git/git.go
index 7e7ba44..1160d0d 100644
--- a/server/git/git.go
+++ b/server/git/git.go
@@ -10,6 +10,8 @@
 	"strconv"
 	"strings"
 	"time"
+
+	"github.com/iomodo/staff/config"
 )
 
 // GitInterface defines the contract for Git operations
@@ -61,6 +63,12 @@
 	UpdatePullRequest(ctx context.Context, id string, options PullRequestOptions) (*PullRequest, error)
 	ClosePullRequest(ctx context.Context, id string) error
 	MergePullRequest(ctx context.Context, id string, options MergePullRequestOptions) error
+
+	// Clone Manager Operations
+	GetAgentClonePath(agentName string) (string, error)
+	RefreshAgentClone(agentName string) error
+	CleanupAgentClone(agentName string) error
+	CleanupAllClones() error
 }
 
 // Status represents the current state of the repository
@@ -187,46 +195,55 @@
 
 // Git implementation using os/exec to call git commands
 type Git struct {
-	repoPath   string
-	config     GitConfig
-	prProvider PullRequestProvider
-	logger     *slog.Logger
-}
-
-// GitConfig holds configuration for Git operations
-type GitConfig struct {
-	Timeout             time.Duration
-	Env                 map[string]string
-	PullRequestProvider PullRequestProvider
+	repoPath     string
+	prProvider   PullRequestProvider
+	cloneManager *CloneManager
+	logger       *slog.Logger
 }
 
 // NewGit creates a new Git instance
-func NewGit(repoPath string, config GitConfig, logger *slog.Logger) GitInterface {
-	if config.Timeout == 0 {
-		config.Timeout = 30 * time.Second
+func New(cfg *config.Config, logger *slog.Logger) GitInterface {
+	var prProvider PullRequestProvider
+	var repoURL string
+
+	switch cfg.GetPrimaryGitProvider() {
+	case "github":
+		githubConfig := GitHubConfig{
+			Token:  cfg.GitHub.Token,
+			Logger: logger,
+		}
+		prProvider = NewGitHubPullRequestProvider(cfg.GitHub.Owner, cfg.GitHub.Repo, githubConfig)
+		repoURL = fmt.Sprintf("https://github.com/%s/%s.git", cfg.GitHub.Owner, cfg.GitHub.Repo)
+		logger.Info("Using GitHub as pull request provider",
+			slog.String("owner", cfg.GitHub.Owner),
+			slog.String("repo", cfg.GitHub.Repo))
+	case "gerrit":
+		gerritConfig := GerritConfig{
+			Username: cfg.Gerrit.Username,
+			Password: cfg.Gerrit.Password,
+			BaseURL:  cfg.Gerrit.BaseURL,
+			Logger:   logger,
+		}
+		prProvider = NewGerritPullRequestProvider(cfg.Gerrit.Project, gerritConfig)
+		repoURL = fmt.Sprintf("%s/%s", cfg.Gerrit.BaseURL, cfg.Gerrit.Project)
+		logger.Info("Using Gerrit as pull request provider",
+			slog.String("base_url", cfg.Gerrit.BaseURL),
+			slog.String("project", cfg.Gerrit.Project))
+	default:
+		panic("no valid Git provider configured")
 	}
 
+	workspacePath := filepath.Join(".", "workspace") //TODO: make it configurable
+	cloneManager := NewCloneManager(repoURL, workspacePath)
+
 	return &Git{
-		repoPath:   repoPath,
-		config:     config,
-		prProvider: config.PullRequestProvider,
-		logger:     logger,
+		repoPath:     cfg.Git.RepoPath,
+		prProvider:   prProvider,
+		cloneManager: cloneManager,
+		logger:       logger,
 	}
 }
 
-// DefaultGit creates a Git instance with default configuration
-func DefaultGit(repoPath string) GitInterface {
-	return NewGit(repoPath, GitConfig{
-		Timeout: 30 * time.Second,
-	}, slog.Default())
-}
-
-// NewGitWithPullRequests creates a Git instance with pull request capabilities
-func NewGitWithPullRequests(repoPath string, config GitConfig, prProvider PullRequestProvider, logger *slog.Logger) GitInterface {
-	config.PullRequestProvider = prProvider
-	return NewGit(repoPath, config, logger)
-}
-
 // Ensure Git implements GitInterface
 var _ GitInterface = (*Git)(nil)
 
@@ -637,6 +654,32 @@
 	return g.prProvider.MergePullRequest(ctx, id, options)
 }
 
+// Clone manage methods
+func (g *Git) GetAgentClonePath(agentName string) (string, error) {
+	if g.cloneManager == nil {
+		return "", &GitError{Command: "GetAgentClonePath", Output: "no clone manager configured"}
+	}
+	return g.cloneManager.GetAgentClonePath(agentName)
+}
+func (g *Git) RefreshAgentClone(agentName string) error {
+	if g.cloneManager == nil {
+		return &GitError{Command: "RefreshAgentClone", Output: "no clone manager configured"}
+	}
+	return g.cloneManager.RefreshAgentClone(agentName)
+}
+func (g *Git) CleanupAgentClone(agentName string) error {
+	if g.cloneManager == nil {
+		return &GitError{Command: "CleanupAgentClone", Output: "no clone manager configured"}
+	}
+	return g.cloneManager.CleanupAgentClone(agentName)
+}
+func (g *Git) CleanupAllClones() error {
+	if g.cloneManager == nil {
+		return &GitError{Command: "CleanupAllClones", Output: "no clone manager configured"}
+	}
+	return g.cloneManager.CleanupAllClones()
+}
+
 // Helper methods
 
 func (g *Git) runCommand(cmd *exec.Cmd, command string) error {
@@ -885,6 +928,7 @@
 	Reviewers   []Author
 	Commits     []Commit
 	Comments    []PullRequestComment
+	URL         string
 }
 
 // PullRequestComment represents a comment on a pull request