package agent

import (
	"context"
	"fmt"
	"log/slog"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"github.com/iomodo/staff/config"
	"github.com/iomodo/staff/git"
	"github.com/iomodo/staff/llm"
	_ "github.com/iomodo/staff/llm/providers" // Auto-register all providers
	"github.com/iomodo/staff/task"
	"github.com/iomodo/staff/tm"
)

// Manager manages multiple AI agents with Git operations and task processing
type Manager struct {
	config         *config.Config
	agents         map[string]*Agent
	taskManager    tm.TaskManager
	autoAssigner   *task.AutoAssigner
	prProvider     git.PullRequestProvider
	cloneManager   *git.CloneManager
	subtaskService *task.SubtaskService
	isRunning      map[string]bool
	stopChannels   map[string]chan struct{}
	logger         *slog.Logger
}

// NewManager creates a new agent manager
func NewManager(cfg *config.Config, taskManager tm.TaskManager, logger *slog.Logger) (*Manager, error) {
	if logger == nil {
		logger = slog.Default()
	}
	// Create auto-assigner
	autoAssigner := task.NewAutoAssigner(cfg.Agents)

	// Create PR provider based on configuration
	var prProvider git.PullRequestProvider
	var repoURL string

	switch cfg.GetPrimaryGitProvider() {
	case "github":
		githubConfig := git.GitHubConfig{
			Token:  cfg.GitHub.Token,
			Logger: logger,
		}
		prProvider = git.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 := git.GerritConfig{
			Username: cfg.Gerrit.Username,
			Password: cfg.Gerrit.Password,
			BaseURL:  cfg.Gerrit.BaseURL,
			Logger:   logger,
		}
		prProvider = git.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:
		return nil, fmt.Errorf("no valid Git provider configured")
	}

	// Create clone manager for per-agent Git repositories
	workspacePath := filepath.Join(".", "workspace")
	cloneManager := git.NewCloneManager(repoURL, workspacePath)

	manager := &Manager{
		config:       cfg,
		agents:       make(map[string]*Agent),
		taskManager:  taskManager,
		autoAssigner: autoAssigner,
		prProvider:   prProvider,
		cloneManager: cloneManager,
		isRunning:    make(map[string]bool),
		stopChannels: make(map[string]chan struct{}),
		logger:       logger,
	}

	// Initialize agents
	if err := manager.initializeAgents(); err != nil {
		return nil, fmt.Errorf("failed to initialize agents: %w", err)
	}

	// Initialize subtask service after agents are created
	if err := manager.initializeSubtaskService(); err != nil {
		return nil, fmt.Errorf("failed to initialize subtask service: %w", err)
	}

	return manager, nil
}

// initializeAgents creates agent instances from configuration
func (m *Manager) initializeAgents() error {
	for _, agentConfig := range m.config.Agents {
		agent, err := m.createAgent(agentConfig)
		if err != nil {
			return fmt.Errorf("failed to create agent %s: %w", agentConfig.Name, err)
		}
		m.agents[agentConfig.Name] = agent
	}
	return nil
}

// initializeSubtaskService creates the subtask service with available agent roles
func (m *Manager) initializeSubtaskService() error {
	// Get agent roles from configuration
	agentRoles := make([]string, 0, len(m.config.Agents))
	for _, agentConfig := range m.config.Agents {
		agentRoles = append(agentRoles, agentConfig.Name)
	}

	// Use the first agent's LLM provider for subtask analysis
	if len(m.agents) == 0 {
		return fmt.Errorf("no agents available for subtask service")
	}

	var firstAgent *Agent
	for _, agent := range m.agents {
		firstAgent = agent
		break
	}

	// Get owner and repo for subtask service based on provider
	var owner, repo string
	switch m.config.GetPrimaryGitProvider() {
	case "github":
		owner = m.config.GitHub.Owner
		repo = m.config.GitHub.Repo
	case "gerrit":
		owner = m.config.Gerrit.Project
		repo = m.config.Gerrit.Project
	}

	m.subtaskService = task.NewSubtaskService(
		firstAgent.Provider,
		m.taskManager,
		agentRoles,
		m.prProvider,
		owner,
		repo,
		m.cloneManager,
		m.logger,
	)

	return nil
}

// createAgent creates a single agent instance
func (m *Manager) createAgent(agentConfig config.AgentConfig) (*Agent, error) {
	// Load system prompt
	systemPrompt, err := m.loadSystemPrompt(agentConfig.SystemPromptFile)
	if err != nil {
		return nil, fmt.Errorf("failed to load system prompt: %w", err)
	}

	// Create LLM provider
	llmConfig := llm.Config{
		Provider: llm.ProviderFake, // Use fake provider for testing
		APIKey:   m.config.OpenAI.APIKey,
		BaseURL:  m.config.OpenAI.BaseURL,
		Timeout:  m.config.OpenAI.Timeout,
	}

	provider, err := llm.CreateProvider(llmConfig)
	if err != nil {
		return nil, fmt.Errorf("failed to create LLM provider: %w", err)
	}

	agent := &Agent{
		Name:         agentConfig.Name,
		Role:         agentConfig.Role,
		Model:        agentConfig.Model,
		SystemPrompt: systemPrompt,
		Provider:     provider,
		MaxTokens:    agentConfig.MaxTokens,
		Temperature:  agentConfig.Temperature,
		Stats:        AgentStats{},
	}

	return agent, nil
}

// loadSystemPrompt loads the system prompt from file
func (m *Manager) loadSystemPrompt(filePath string) (string, error) {
	content, err := os.ReadFile(filePath)
	if err != nil {
		return "", fmt.Errorf("failed to read system prompt file %s: %w", filePath, err)
	}
	return string(content), nil
}

// StartAgent starts an agent to process tasks in a loop
func (m *Manager) StartAgent(agentName string, loopInterval time.Duration) error {
	agent, exists := m.agents[agentName]
	if !exists {
		return fmt.Errorf("agent %s not found", agentName)
	}

	if m.isRunning[agentName] {
		return fmt.Errorf("agent %s is already running", agentName)
	}

	stopChan := make(chan struct{})
	m.stopChannels[agentName] = stopChan
	m.isRunning[agentName] = true

	go m.runAgentLoop(agent, loopInterval, stopChan)

	m.logger.Info("Started agent",
		slog.String("name", agentName),
		slog.String("role", agent.Role),
		slog.String("model", agent.Model))
	return nil
}

// StopAgent stops a running agent
func (m *Manager) StopAgent(agentName string) error {
	if !m.isRunning[agentName] {
		return fmt.Errorf("agent %s is not running", agentName)
	}

	close(m.stopChannels[agentName])
	delete(m.stopChannels, agentName)
	m.isRunning[agentName] = false

	m.logger.Info("Stopped agent", slog.String("name", agentName))
	return nil
}

// runAgentLoop runs the main processing loop for an agent
func (m *Manager) runAgentLoop(agent *Agent, interval time.Duration, stopChan <-chan struct{}) {
	ticker := time.NewTicker(interval)
	defer ticker.Stop()

	for {
		select {
		case <-stopChan:
			m.logger.Info("Agent stopping", slog.String("name", agent.Name))
			return
		case <-ticker.C:
			if err := m.processAgentTasks(agent); err != nil {
				m.logger.Error("Error processing tasks for agent",
					slog.String("agent", agent.Name),
					slog.String("error", err.Error()))
			}
		}
	}
}

// processAgentTasks processes all assigned tasks for an agent
func (m *Manager) processAgentTasks(agent *Agent) error {
	if agent.CurrentTask != nil {
		return nil
	}

	// Get tasks assigned to this agent
	tasks, err := m.taskManager.GetTasksByAssignee(agent.Name)
	if err != nil {
		return fmt.Errorf("failed to get tasks for agent %s: %w", agent.Name, err)
	}

	m.logger.Info("Processing tasks for agent",
		slog.Int("task_count", len(tasks)),
		slog.String("agent", agent.Name))

	for _, task := range tasks {
		if task.Status == tm.StatusToDo || task.Status == tm.StatusPending {
			if err := m.processTask(agent, task); err != nil {
				m.logger.Error("Error processing task",
					slog.String("task_id", task.ID),
					slog.String("error", err.Error()))
				// Mark task as failed
				task.Status = tm.StatusFailed
				if err := m.taskManager.UpdateTask(task); err != nil {
					m.logger.Error("Error updating failed task",
						slog.String("task_id", task.ID),
						slog.String("error", err.Error()))
				}
				agent.Stats.TasksFailed++
			} else {
				agent.Stats.TasksCompleted++
			}
			// Update success rate
			total := agent.Stats.TasksCompleted + agent.Stats.TasksFailed
			if total > 0 {
				agent.Stats.SuccessRate = float64(agent.Stats.TasksCompleted) / float64(total) * 100
			}
		}
	}

	return nil
}

// processTask processes a single task with an agent
func (m *Manager) processTask(agent *Agent, task *tm.Task) error {
	ctx := context.Background()
	startTime := time.Now()

	m.logger.Info("Agent processing task",
		slog.String("agent", agent.Name),
		slog.String("task_id", task.ID),
		slog.String("title", task.Title))

	// Mark task as in progress
	task.Status = tm.StatusInProgress
	agent.CurrentTask = &task.ID
	if err := m.taskManager.UpdateTask(task); err != nil {
		return fmt.Errorf("failed to update task status: %w", err)
	}

	// Check if this task should generate subtasks (with LLM decision)
	if m.shouldGenerateSubtasks(task) {
		m.logger.Info("LLM determined task should generate subtasks", slog.String("task_id", task.ID))
		if err := m.generateSubtasksForTask(ctx, task); err != nil {
			m.logger.Warn("Failed to generate subtasks for task",
				slog.String("task_id", task.ID),
				slog.String("error", err.Error()))
			// Continue with normal processing if subtask generation fails
		} else {
			// Task has been converted to subtask management, mark as completed
			task.Status = tm.StatusCompleted
			task.Solution = "Task analyzed by LLM and broken down into subtasks with potential new agent creation. See subtasks PR for details."
			completedAt := time.Now()
			task.CompletedAt = &completedAt
			agent.CurrentTask = nil

			if err := m.taskManager.UpdateTask(task); err != nil {
				return fmt.Errorf("failed to update task with subtasks: %w", err)
			}

			m.logger.Info("Task converted to subtasks by agent using LLM analysis",
				slog.String("task_id", task.ID),
				slog.String("agent", agent.Name))
			return nil
		}
	}

	// Generate solution using LLM
	solution, err := m.generateSolution(ctx, agent, task)
	if err != nil {
		return fmt.Errorf("failed to generate solution: %w", err)
	}

	// Create Git branch and commit solution
	branchName := m.generateBranchName(task)
	if err := m.createAndCommitSolution(branchName, task, solution, agent); err != nil {
		return fmt.Errorf("failed to commit solution: %w", err)
	}

	// Create pull request
	prURL, err := m.createPullRequest(ctx, task, solution, agent, branchName)
	if err != nil {
		return fmt.Errorf("failed to create pull request: %w", err)
	}

	// Update task as completed
	task.Status = tm.StatusCompleted
	task.Solution = solution
	task.PullRequestURL = prURL
	completedAt := time.Now()
	task.CompletedAt = &completedAt
	agent.CurrentTask = nil

	if err := m.taskManager.UpdateTask(task); err != nil {
		return fmt.Errorf("failed to update completed task: %w", err)
	}

	// Update agent stats
	duration := time.Since(startTime)
	if agent.Stats.AvgTime == 0 {
		agent.Stats.AvgTime = duration.Milliseconds()
	} else {
		agent.Stats.AvgTime = (agent.Stats.AvgTime + duration.Milliseconds()) / 2
	}

	m.logger.Info("Task completed by agent",
		slog.String("task_id", task.ID),
		slog.String("agent", agent.Name),
		slog.Duration("duration", duration),
		slog.String("pr_url", prURL))
	return nil
}

// generateSolution uses the agent's LLM to generate a solution
func (m *Manager) generateSolution(ctx context.Context, agent *Agent, task *tm.Task) (string, error) {
	prompt := m.buildTaskPrompt(task)

	req := llm.ChatCompletionRequest{
		Model: agent.Model,
		Messages: []llm.Message{
			{
				Role:    llm.RoleSystem,
				Content: agent.SystemPrompt,
			},
			{
				Role:    llm.RoleUser,
				Content: prompt,
			},
		},
		MaxTokens:   agent.MaxTokens,
		Temperature: agent.Temperature,
	}

	resp, err := agent.Provider.ChatCompletion(ctx, req)
	if err != nil {
		return "", fmt.Errorf("LLM request failed: %w", err)
	}

	if len(resp.Choices) == 0 {
		return "", fmt.Errorf("no response from LLM")
	}

	return resp.Choices[0].Message.Content, nil
}

// buildTaskPrompt creates a detailed prompt for the LLM
func (m *Manager) buildTaskPrompt(task *tm.Task) string {
	return fmt.Sprintf(`Task: %s

Priority: %s
Description: %s

Please provide a complete solution for this task. Include:
1. Detailed implementation plan
2. Code changes needed (if applicable)
3. Files to be created or modified
4. Testing considerations
5. Any dependencies or prerequisites

Your response should be comprehensive and actionable.`,
		task.Title,
		task.Priority,
		task.Description)
}

// generateBranchName creates a Git branch name for the task
func (m *Manager) generateBranchName(task *tm.Task) string {
	// Clean title for use in branch name
	cleanTitle := strings.ToLower(task.Title)
	cleanTitle = strings.ReplaceAll(cleanTitle, " ", "-")
	cleanTitle = strings.ReplaceAll(cleanTitle, "/", "-")
	// Remove special characters
	var result strings.Builder
	for _, r := range cleanTitle {
		if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '-' {
			result.WriteRune(r)
		}
	}
	cleanTitle = result.String()

	// Limit length
	if len(cleanTitle) > 40 {
		cleanTitle = cleanTitle[:40]
	}

	return fmt.Sprintf("%s%s-%s", m.config.Git.BranchPrefix, task.ID, cleanTitle)
}

// createAndCommitSolution creates a Git branch and commits the solution using per-agent clones
func (m *Manager) createAndCommitSolution(branchName string, task *tm.Task, solution string, agent *Agent) error {
	ctx := context.Background()

	// Get agent's dedicated Git clone
	clonePath, err := m.cloneManager.GetAgentClonePath(agent.Name)
	if err != nil {
		return fmt.Errorf("failed to get agent clone: %w", err)
	}

	m.logger.Info("Agent working in clone",
		slog.String("agent", agent.Name),
		slog.String("clone_path", clonePath))

	// Refresh the clone with latest changes
	if err := m.cloneManager.RefreshAgentClone(agent.Name); err != nil {
		m.logger.Warn("Failed to refresh clone for agent",
			slog.String("agent", agent.Name),
			slog.String("error", err.Error()))
	}

	// All Git operations use the agent's clone directory
	gitCmd := func(args ...string) *exec.Cmd {
		return exec.CommandContext(ctx, "git", append([]string{"-C", clonePath}, args...)...)
	}

	// Ensure we're on main branch before creating new branch
	cmd := gitCmd("checkout", "main")
	if err := cmd.Run(); err != nil {
		// Try master branch if main doesn't exist
		cmd = gitCmd("checkout", "master")
		if err := cmd.Run(); err != nil {
			return fmt.Errorf("failed to checkout main/master branch: %w", err)
		}
	}

	// Create branch
	cmd = gitCmd("checkout", "-b", branchName)
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("failed to create branch: %w", err)
	}

	// Create solution file in agent's clone
	solutionDir := filepath.Join(clonePath, "tasks", "solutions")
	if err := os.MkdirAll(solutionDir, 0755); err != nil {
		return fmt.Errorf("failed to create solution directory: %w", err)
	}

	solutionFile := filepath.Join(solutionDir, fmt.Sprintf("%s-solution.md", task.ID))
	solutionContent := fmt.Sprintf(`# Solution for Task: %s

**Agent:** %s (%s)  
**Model:** %s  
**Completed:** %s

## Task Description
%s

## Solution
%s

---
*Generated by Staff AI Agent System*
`, task.Title, agent.Name, agent.Role, agent.Model, time.Now().Format(time.RFC3339), task.Description, solution)

	if err := os.WriteFile(solutionFile, []byte(solutionContent), 0644); err != nil {
		return fmt.Errorf("failed to write solution file: %w", err)
	}

	// Stage files
	relativeSolutionFile := filepath.Join("tasks", "solutions", fmt.Sprintf("%s-solution.md", task.ID))
	cmd = gitCmd("add", relativeSolutionFile)
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("failed to stage files: %w", err)
	}

	// Commit changes
	commitMsg := m.buildCommitMessage(task, agent)
	cmd = gitCmd("commit", "-m", commitMsg)
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("failed to commit: %w", err)
	}

	// Push branch
	cmd = gitCmd("push", "-u", "origin", branchName)
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("failed to push branch: %w", err)
	}

	m.logger.Info("Agent successfully pushed branch",
		slog.String("agent", agent.Name),
		slog.String("branch", branchName))
	return nil
}

// buildCommitMessage creates a commit message from template
func (m *Manager) buildCommitMessage(task *tm.Task, agent *Agent) string {
	template := m.config.Git.CommitMessageTemplate

	replacements := map[string]string{
		"{task_id}":    task.ID,
		"{task_title}": task.Title,
		"{agent_name}": agent.Name,
		"{solution}":   "See solution file for details",
	}

	result := template
	for placeholder, value := range replacements {
		result = strings.ReplaceAll(result, placeholder, value)
	}

	return result
}

// createPullRequest creates a GitHub pull request
func (m *Manager) createPullRequest(ctx context.Context, task *tm.Task, solution string, agent *Agent, branchName string) (string, error) {
	title := fmt.Sprintf("Task %s: %s", task.ID, task.Title)

	// Build PR description from template
	description := m.buildPRDescription(task, solution, agent)

	options := git.PullRequestOptions{
		Title:       title,
		Description: description,
		HeadBranch:  branchName,
		BaseBranch:  "main",
		Labels:      []string{"ai-generated", "staff-agent", strings.ToLower(agent.Role)},
		Draft:       false,
	}

	pr, err := m.prProvider.CreatePullRequest(ctx, options)
	if err != nil {
		return "", fmt.Errorf("failed to create PR: %w", err)
	}

	// Generate provider-specific PR URL
	switch m.config.GetPrimaryGitProvider() {
	case "github":
		return fmt.Sprintf("https://github.com/%s/%s/pull/%d", m.config.GitHub.Owner, m.config.GitHub.Repo, pr.Number), nil
	case "gerrit":
		return fmt.Sprintf("%s/c/%s/+/%d", m.config.Gerrit.BaseURL, m.config.Gerrit.Project, pr.Number), nil
	default:
		return "", fmt.Errorf("unknown git provider")
	}
}

// buildPRDescription creates PR description from template
func (m *Manager) buildPRDescription(task *tm.Task, solution string, agent *Agent) string {
	template := m.config.Git.PRTemplate

	// Truncate solution for PR if too long
	truncatedSolution := solution
	if len(solution) > 1000 {
		truncatedSolution = solution[:1000] + "...\n\n*See solution file for complete details*"
	}

	replacements := map[string]string{
		"{task_id}":          task.ID,
		"{task_title}":       task.Title,
		"{task_description}": task.Description,
		"{agent_name}":       fmt.Sprintf("%s (%s)", agent.Name, agent.Role),
		"{priority}":         string(task.Priority),
		"{solution}":         truncatedSolution,
		"{files_changed}":    fmt.Sprintf("- `tasks/solutions/%s-solution.md`", task.ID),
	}

	result := template
	for placeholder, value := range replacements {
		result = strings.ReplaceAll(result, placeholder, value)
	}

	return result
}

// AutoAssignTask automatically assigns a task to the best matching agent
func (m *Manager) AutoAssignTask(taskID string) error {
	task, err := m.taskManager.GetTask(taskID)
	if err != nil {
		return fmt.Errorf("failed to get task: %w", err)
	}

	agentName, err := m.autoAssigner.AssignTask(task)
	if err != nil {
		return fmt.Errorf("failed to auto-assign task: %w", err)
	}

	task.Assignee = agentName
	if err := m.taskManager.UpdateTask(task); err != nil {
		return fmt.Errorf("failed to update task assignment: %w", err)
	}

	explanation := m.autoAssigner.GetRecommendationExplanation(task, agentName)
	m.logger.Info("Auto-assigned task to agent",
		slog.String("task_id", taskID),
		slog.String("agent", agentName),
		slog.String("explanation", explanation))

	return nil
}

// GetAgentStatus returns the status of all agents
func (m *Manager) GetAgentStatus() map[string]AgentInfo {
	status := make(map[string]AgentInfo)

	for name, agent := range m.agents {
		agentStatus := StatusIdle
		if m.isRunning[name] {
			if agent.CurrentTask != nil {
				agentStatus = StatusRunning
			}
		} else {
			agentStatus = StatusStopped
		}

		status[name] = AgentInfo{
			Name:        agent.Name,
			Role:        agent.Role,
			Model:       agent.Model,
			Status:      agentStatus,
			CurrentTask: agent.CurrentTask,
			Stats:       agent.Stats,
		}
	}

	return status
}

// shouldGenerateSubtasks determines if a task should be broken down into subtasks using LLM
func (m *Manager) shouldGenerateSubtasks(task *tm.Task) bool {
	// Don't generate subtasks for subtasks
	if task.ParentTaskID != "" {
		return false
	}

	// Don't generate if already evaluated
	if task.SubtasksEvaluated {
		return false
	}

	// Ask LLM to decide
	ctx := context.Background()
	decision, err := m.subtaskService.ShouldGenerateSubtasks(ctx, task)
	if err != nil {
		m.logger.Warn("Failed to get LLM subtask decision for task",
			slog.String("task_id", task.ID),
			slog.String("error", err.Error()))
		// Fallback to simple heuristics
		return task.Priority == tm.PriorityHigh || len(task.Description) > 200
	}

	// Update task to mark as evaluated
	task.SubtasksEvaluated = true
	if err := m.taskManager.UpdateTask(task); err != nil {
		m.logger.Warn("Failed to update task evaluation status", slog.String("error", err.Error()))
	}

	m.logger.Info("LLM subtask decision for task",
		slog.String("task_id", task.ID),
		slog.Bool("needs_subtasks", decision.NeedsSubtasks),
		slog.Int("complexity_score", decision.ComplexityScore),
		slog.String("reasoning", decision.Reasoning))

	return decision.NeedsSubtasks
}

// generateSubtasksForTask analyzes a task and creates a PR with proposed subtasks
func (m *Manager) generateSubtasksForTask(ctx context.Context, task *tm.Task) error {
	if m.subtaskService == nil {
		return fmt.Errorf("subtask service not initialized")
	}

	// Analyze the task for subtasks
	analysis, err := m.subtaskService.AnalyzeTaskForSubtasks(ctx, task)
	if err != nil {
		return fmt.Errorf("failed to analyze task for subtasks: %w", err)
	}

	// Generate a PR with the subtask proposals
	prURL, err := m.subtaskService.GenerateSubtaskPR(ctx, analysis)
	if err != nil {
		return fmt.Errorf("failed to generate subtask PR: %w", err)
	}

	// Update the task with subtask information
	task.SubtasksPRURL = prURL
	task.SubtasksGenerated = true

	m.logger.Info("Generated subtask PR for task",
		slog.String("task_id", task.ID),
		slog.String("pr_url", prURL))
	m.logger.Info("Proposed subtasks and new agents for task",
		slog.String("task_id", task.ID),
		slog.Int("subtask_count", len(analysis.Subtasks)),
		slog.Int("new_agent_count", len(analysis.AgentCreations)))

	// Log proposed new agents if any
	if len(analysis.AgentCreations) > 0 {
		for _, agent := range analysis.AgentCreations {
			m.logger.Info("Proposed new agent",
				slog.String("role", agent.Role),
				slog.Any("skills", agent.Skills))
		}
	}

	return nil
}

// IsAgentRunning checks if an agent is currently running
func (m *Manager) IsAgentRunning(agentName string) bool {
	return m.isRunning[agentName]
}

// Close shuts down the agent manager
func (m *Manager) Close() error {
	// Stop all running agents
	for agentName := range m.isRunning {
		if m.isRunning[agentName] {
			m.StopAgent(agentName)
		}
	}

	// Close all LLM providers
	for _, agent := range m.agents {
		if err := agent.Provider.Close(); err != nil {
			m.logger.Error("Error closing provider for agent",
				slog.String("agent", agent.Name),
				slog.String("error", err.Error()))
		}
	}

	// Cleanup all agent Git clones
	if err := m.cloneManager.CleanupAllClones(); err != nil {
		m.logger.Error("Error cleaning up agent clones", slog.String("error", err.Error()))
	}

	// Cleanup subtask service
	if m.subtaskService != nil {
		if err := m.subtaskService.Close(); err != nil {
			m.logger.Error("Error closing subtask service", slog.String("error", err.Error()))
		}
	}

	return nil
}
