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 {
			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

	// 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()))
		} else {
			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 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
	}

	task.SubtasksEvaluated = true
	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
}
