package service

import (
	"context"
	"fmt"

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

// SDLCCallbackService handles build completion callbacks to update SDLC artifact status.
type SDLCCallbackService struct {
	sdlcService *SDLCService
}

// NewSDLCCallbackService creates a new SDLC callback service.
func NewSDLCCallbackService(sdlcService *SDLCService) *SDLCCallbackService {
	return &SDLCCallbackService{
		sdlcService: sdlcService,
	}
}

// HandleCallback processes a build completion and updates SDLC artifact status.
func (s *SDLCCallbackService) HandleCallback(ctx context.Context, payload *domain.SDLCCallbackPayload) error {
	// Validate required fields
	if payload.ProjectID == "" {
		return fmt.Errorf("project_id is required")
	}
	if payload.Feature == "" {
		return fmt.Errorf("feature is required")
	}
	if payload.ArtifactType == "" {
		return fmt.Errorf("artifact_type is required")
	}

	// Map generate artifact type to SDLC artifact type
	artType, err := s.mapArtifactType(payload.ArtifactType)
	if err != nil {
		return fmt.Errorf("invalid artifact_type: %w", err)
	}

	log := logging.FromContext(ctx).WithService("sdlc_callback")
	log.Info("handling SDLC callback",
		"task_id", payload.TaskID,
		logging.FieldProjectID, payload.ProjectID,
		"feature", payload.Feature,
		"artifact_type", payload.ArtifactType,
		"success", payload.Success,
	)

	if payload.Success {
		// QA results get "passed" status, others get "draft" (awaiting human approval)
		if artType == sdlc.ArtifactQAResults {
			if err := s.sdlcService.PassArtifact(ctx, payload.ProjectID, payload.Feature, artType); err != nil {
				log.Error("failed to pass artifact",
					logging.FieldError, err,
					logging.FieldProjectID, payload.ProjectID,
					"feature", payload.Feature,
					"artifact_type", artType,
				)
				return fmt.Errorf("pass artifact: %w", err)
			}
			log.Info("artifact marked as passed",
				logging.FieldProjectID, payload.ProjectID,
				"feature", payload.Feature,
				"artifact_type", artType,
			)
		} else {
			// Mark as draft - awaiting human approval
			// The SDLC service doesn't have a direct setDraft method, but we can
			// achieve this by first ensuring the artifact exists, then the file
			// generation creates the draft status automatically.
			// For now, we'll log that the artifact was generated.
			log.Info("artifact generated successfully (draft status)",
				logging.FieldProjectID, payload.ProjectID,
				"feature", payload.Feature,
				"artifact_type", artType,
				"commit_sha", payload.CommitSHA,
			)
		}
	} else {
		// Mark as needs_fix on failure
		if err := s.sdlcService.NeedsFixArtifact(ctx, payload.ProjectID, payload.Feature, artType); err != nil {
			log.Error("failed to mark artifact as needs_fix",
				logging.FieldError, err,
				logging.FieldProjectID, payload.ProjectID,
				"feature", payload.Feature,
				"artifact_type", artType,
			)
			return fmt.Errorf("needs_fix artifact: %w", err)
		}
		log.Info("artifact marked as needs_fix",
			logging.FieldProjectID, payload.ProjectID,
			"feature", payload.Feature,
			"artifact_type", artType,
			logging.FieldError, payload.Error,
		)
	}

	return nil
}

// mapArtifactType converts generate artifact types to SDLC artifact types.
func (s *SDLCCallbackService) mapArtifactType(genType string) (sdlc.ArtifactType, error) {
	switch genType {
	case "spec":
		return sdlc.ArtifactSpec, nil
	case "design":
		return sdlc.ArtifactDesign, nil
	case "tasks":
		return sdlc.ArtifactTasks, nil
	case "code":
		// Code generation doesn't map to a single artifact type
		// The code is committed directly, no artifact status change needed
		return "", fmt.Errorf("code artifact type does not have a corresponding SDLC artifact")
	case "qa":
		return sdlc.ArtifactQAResults, nil
	default:
		return "", fmt.Errorf("unknown artifact type: %s", genType)
	}
}
