package git

import (
	"context"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"sync"
)

// CloneManager manages separate Git repository clones for each agent
// This eliminates Git concurrency issues by giving each agent its own working directory
type CloneManager struct {
	baseRepoURL    string
	workspacePath  string
	agentClones    map[string]string // agent name -> clone path
	mu             sync.RWMutex
}

// NewCloneManager creates a new CloneManager
func NewCloneManager(baseRepoURL, workspacePath string) *CloneManager {
	return &CloneManager{
		baseRepoURL:   baseRepoURL,
		workspacePath: workspacePath,
		agentClones:   make(map[string]string),
	}
}

// GetAgentClonePath returns the Git clone path for a specific agent
// Creates the clone if it doesn't exist
func (cm *CloneManager) GetAgentClonePath(agentName string) (string, error) {
	cm.mu.Lock()
	defer cm.mu.Unlock()

	// Check if clone already exists
	if clonePath, exists := cm.agentClones[agentName]; exists {
		// Verify the clone still exists on disk
		if _, err := os.Stat(clonePath); err == nil {
			return clonePath, nil
		}
		// Remove stale entry if directory doesn't exist
		delete(cm.agentClones, agentName)
	}

	// Create new clone for the agent
	clonePath := filepath.Join(cm.workspacePath, fmt.Sprintf("agent-%s", agentName))
	
	// Ensure workspace directory exists
	if err := os.MkdirAll(cm.workspacePath, 0755); err != nil {
		return "", fmt.Errorf("failed to create workspace directory: %w", err)
	}

	// Remove existing clone directory if it exists
	if err := os.RemoveAll(clonePath); err != nil {
		return "", fmt.Errorf("failed to remove existing clone: %w", err)
	}

	// Clone the repository
	if err := cm.cloneRepository(clonePath); err != nil {
		return "", fmt.Errorf("failed to clone repository for agent %s: %w", agentName, err)
	}

	// Store the clone path
	cm.agentClones[agentName] = clonePath
	
	return clonePath, nil
}

// cloneRepository performs the actual Git clone operation
func (cm *CloneManager) cloneRepository(clonePath string) error {
	ctx := context.Background()
	
	// Clone the repository
	cmd := exec.CommandContext(ctx, "git", "clone", cm.baseRepoURL, clonePath)
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("git clone failed: %w", err)
	}

	return nil
}

// RefreshAgentClone pulls the latest changes for an agent's clone
func (cm *CloneManager) RefreshAgentClone(agentName string) error {
	cm.mu.RLock()
	clonePath, exists := cm.agentClones[agentName]
	cm.mu.RUnlock()

	if !exists {
		return fmt.Errorf("no clone exists for agent %s", agentName)
	}

	ctx := context.Background()
	
	// Change to clone directory and pull latest changes
	cmd := exec.CommandContext(ctx, "git", "-C", clonePath, "pull", "origin")
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("failed to pull latest changes for agent %s: %w", agentName, err)
	}

	return nil
}

// CleanupAgentClone removes the clone directory for an agent
func (cm *CloneManager) CleanupAgentClone(agentName string) error {
	cm.mu.Lock()
	defer cm.mu.Unlock()

	clonePath, exists := cm.agentClones[agentName]
	if !exists {
		return nil // Already cleaned up
	}

	// Remove the clone directory
	if err := os.RemoveAll(clonePath); err != nil {
		return fmt.Errorf("failed to remove clone for agent %s: %w", agentName, err)
	}

	// Remove from tracking
	delete(cm.agentClones, agentName)
	
	return nil
}

// CleanupAllClones removes all agent clone directories
func (cm *CloneManager) CleanupAllClones() error {
	cm.mu.Lock()
	defer cm.mu.Unlock()

	var errors []error
	
	for agentName, clonePath := range cm.agentClones {
		if err := os.RemoveAll(clonePath); err != nil {
			errors = append(errors, fmt.Errorf("failed to remove clone for agent %s: %w", agentName, err))
		}
	}

	// Clear all tracked clones
	cm.agentClones = make(map[string]string)

	if len(errors) > 0 {
		return fmt.Errorf("cleanup errors: %v", errors)
	}

	return nil
}

// GetAllAgentClones returns a map of all agent clones
func (cm *CloneManager) GetAllAgentClones() map[string]string {
	cm.mu.RLock()
	defer cm.mu.RUnlock()

	// Return a copy to avoid race conditions
	result := make(map[string]string)
	for agent, path := range cm.agentClones {
		result[agent] = path
	}
	
	return result
}