// Package service provides business logic services.
package service

import (
	"context"
	"fmt"

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

// VerifyService orchestrates verify task submission and tracking.
// It coordinates between the work queue (execution) for visual captures.
type VerifyService struct {
	queue port.WorkQueue
}

// NewVerifyService creates a new verify service.
func NewVerifyService(queue port.WorkQueue) *VerifyService {
	return &VerifyService{
		queue: queue,
	}
}

// SubmitCapture validates spec and enqueues a verify task.
// Returns the task ID for status tracking.
func (s *VerifyService) SubmitCapture(ctx context.Context, projectID string, spec domain.VerifySpec) (string, error) {
	if err := spec.Validate(); err != nil {
		return "", fmt.Errorf("invalid verify spec: %w", err)
	}

	if projectID == "" {
		return "", fmt.Errorf("project_id is required")
	}

	// Apply defaults
	specWithDefaults := spec.WithDefaults()

	// Build work task spec from verify spec
	taskSpec := map[string]any{
		"url":          specWithDefaults.URL,
		"viewports":    specWithDefaults.Viewports,
		"wait_for":     specWithDefaults.WaitFor,
		"wait_timeout": specWithDefaults.WaitTimeout,
		"full_page":    specWithDefaults.FullPage,
		"video":        specWithDefaults.Video,
	}
	if specWithDefaults.Evaluate {
		taskSpec["evaluate"] = specWithDefaults.Evaluate
	}
	if specWithDefaults.Prompt != "" {
		taskSpec["prompt"] = specWithDefaults.Prompt
	}
	if specWithDefaults.CallbackURL != "" {
		taskSpec["callback_url"] = specWithDefaults.CallbackURL
	}

	// Create work task
	task := &domain.WorkTask{
		ProjectID:   projectID,
		Type:        domain.WorkTaskTypeVerify,
		Spec:        taskSpec,
		CallbackURL: specWithDefaults.CallbackURL,
		MaxRetries:  1, // Verify tasks shouldn't retry by default
	}

	// Enqueue to work queue
	taskID, err := s.queue.Enqueue(ctx, task)
	if err != nil {
		return "", fmt.Errorf("enqueue verify task: %w", err)
	}

	log := logging.FromContext(ctx).WithService("verify")
	log.Info("verify task enqueued",
		"task_id", taskID,
		logging.FieldProjectID, projectID,
		"url", specWithDefaults.URL,
		"viewports", specWithDefaults.Viewports,
	)

	return taskID, nil
}

// GetCapture retrieves a verify task by ID.
func (s *VerifyService) GetCapture(ctx context.Context, taskID string) (*domain.WorkTask, error) {
	task, err := s.queue.GetTask(ctx, taskID)
	if err != nil {
		return nil, err
	}

	// Verify it's actually a verify task
	if task.Type != domain.WorkTaskTypeVerify {
		return nil, domain.ErrWorkTaskNotFound
	}

	return task, nil
}

// ListCaptures returns verify tasks for a project.
func (s *VerifyService) ListCaptures(ctx context.Context, projectID string, opts domain.WorkListOptions) (*domain.WorkListResult, error) {
	opts.Normalize()

	// Get all tasks for the project
	result, err := s.queue.ListByProject(ctx, projectID, nil, opts)
	if err != nil {
		return nil, err
	}

	// Filter to only verify tasks
	var verifyTasks []*domain.WorkTask
	for _, task := range result.Tasks {
		if task.Type == domain.WorkTaskTypeVerify {
			verifyTasks = append(verifyTasks, task)
		}
	}

	return &domain.WorkListResult{
		Tasks:  verifyTasks,
		Total:  int64(len(verifyTasks)), // Note: this is filtered total, not DB total
		Limit:  result.Limit,
		Offset: result.Offset,
	}, nil
}

// CancelCapture cancels a pending verify task.
func (s *VerifyService) CancelCapture(ctx context.Context, taskID string) error {
	// Verify it's a verify task first
	task, err := s.queue.GetTask(ctx, taskID)
	if err != nil {
		return err
	}

	if task.Type != domain.WorkTaskTypeVerify {
		return domain.ErrWorkTaskNotFound
	}

	return s.queue.Cancel(ctx, taskID)
}
