// Package service provides business logic / use cases for the application.
// This file contains command queue functionality for async task execution.
package service

import (
	"context"
	"fmt"

	"github.com/orchard9/rdev/internal/domain"
)

// EnqueueCommandRequest contains parameters for enqueueing a command.
type EnqueueCommandRequest struct {
	ProjectID   domain.ProjectID
	Command     string
	CommandType domain.CommandType
	WorkingDir  string
	Priority    int
	Audit       *AuditContext
}

// EnqueueCommandResult contains the result of enqueueing a command.
type EnqueueCommandResult struct {
	CommandID domain.QueuedCommandID
	StreamURL string
	Position  int
}

// EnqueueCommand adds a command to the project's queue for async execution.
// Returns an error if no queue is configured.
func (s *ProjectService) EnqueueCommand(ctx context.Context, req EnqueueCommandRequest) (*EnqueueCommandResult, error) {
	if s.queue == nil {
		return nil, fmt.Errorf("command queue not configured")
	}

	// Validate project exists
	exists, err := s.projects.Exists(ctx, req.ProjectID)
	if err != nil {
		return nil, err
	}
	if !exists {
		return nil, domain.ErrProjectNotFound
	}

	// Create queued command
	cmd := &domain.QueuedCommand{
		ProjectID:   string(req.ProjectID),
		Command:     req.Command,
		CommandType: req.CommandType,
		WorkingDir:  req.WorkingDir,
		Status:      domain.QueueStatusPending,
		Priority:    req.Priority,
	}
	if req.Audit != nil {
		cmd.APIKeyID = req.Audit.APIKeyID
	}

	// Enqueue
	if err := s.queue.Enqueue(ctx, cmd); err != nil {
		return nil, fmt.Errorf("enqueue command: %w", err)
	}

	// Get approximate position
	pendingStatus := domain.QueueStatusPending
	pending, _ := s.queue.List(ctx, string(req.ProjectID), &domain.QueueFilters{
		Status:    &pendingStatus,
		Limit:     1000,
		SortOrder: "asc",
	})

	return &EnqueueCommandResult{
		CommandID: cmd.ID,
		StreamURL: fmt.Sprintf("/projects/%s/events?stream_id=%s", req.ProjectID, cmd.ID),
		Position:  len(pending),
	}, nil
}

// GetQueuedCommand retrieves a queued command by ID.
func (s *ProjectService) GetQueuedCommand(ctx context.Context, cmdID domain.QueuedCommandID) (*domain.QueuedCommand, error) {
	if s.queue == nil {
		return nil, fmt.Errorf("command queue not configured")
	}
	return s.queue.GetByID(ctx, cmdID)
}

// ListQueuedCommands returns queued commands for a project.
func (s *ProjectService) ListQueuedCommands(ctx context.Context, projectID domain.ProjectID, filters *domain.QueueFilters) ([]*domain.QueuedCommand, error) {
	if s.queue == nil {
		return nil, fmt.Errorf("command queue not configured")
	}
	return s.queue.List(ctx, string(projectID), filters)
}

// CancelQueuedCommand cancels a pending queued command.
func (s *ProjectService) CancelQueuedCommand(ctx context.Context, cmdID domain.QueuedCommandID) error {
	if s.queue == nil {
		return fmt.Errorf("command queue not configured")
	}
	return s.queue.Cancel(ctx, cmdID)
}

// GetQueueStats returns queue statistics for a project.
func (s *ProjectService) GetQueueStats(ctx context.Context, projectID domain.ProjectID) (*domain.QueueStats, error) {
	if s.queue == nil {
		return nil, fmt.Errorf("command queue not configured")
	}
	return s.queue.GetStats(ctx, string(projectID))
}
