package run

import (
	"github.com/gin-gonic/gin"

	"github.com/tidbcloud/AgentTeam/internal/api"
	"github.com/tidbcloud/AgentTeam/internal/api/dto"
)

type Dependencies struct {
	AuthStore                 api.SessionAuthenticator
	WorkspaceStore            api.WorkspaceResolver
	EmailVerificationRequired bool
	Service                   Service
	Calendar                  CalendarService
}

func handleWorkspace(handler api.WorkspaceScopedHandler) gin.HandlerFunc {
	return api.HandleWorkspaceScoped(handler, api.WithErrorClassifier(classifyError))
}

func handleCancel(handler func(api.WorkspaceScopedJSON[dto.WorkflowRunCancelActionRequest]) (api.Response, error)) gin.HandlerFunc {
	return api.HandleWorkspaceScoped(func(request api.WorkspaceScopedRequest) (api.Response, error) {
		body, err := decodeWorkflowRunCancelJSON(request.Gin)
		if err != nil {
			return api.Response{}, err
		}
		return handler(api.WorkspaceScopedJSON[dto.WorkflowRunCancelActionRequest]{
			WorkspaceScopedRequest: request,
			Body:                   body,
		})
	}, api.WithErrorClassifier(classifyError))
}

// RegisterRoutes mounts the complete human Run lifecycle. Runs have no human
// create/update/delete/archive operations: Invocation acceptance creates them,
// runtime advances them, and humans can observe or cancel them.
func RegisterRoutes(router gin.IRouter, dependencies Dependencies) {
	if router == nil || (dependencies.Service == nil && dependencies.Calendar == nil) {
		return
	}
	workspaceScoped := router.Group(
		"/api/v1/workspaces/:workspaceId",
		api.RequireAuthenticatedUser(dependencies.AuthStore),
		api.RequireVerifiedIdentity(dependencies.EmailVerificationRequired),
		api.RequireRouteWorkspace(dependencies.WorkspaceStore),
	)
	if dependencies.Calendar != nil {
		calendar := NewCalendarHandler(dependencies.Calendar)
		workspaceScoped.GET("/workflow/calendar", handleWorkspace(calendar.List))
	}
	if dependencies.Service != nil {
		handler := NewHandler(dependencies.Service)
		workspaceScoped.GET("/workflow/runs", handleWorkspace(handler.List))
		workspaceScoped.GET("/workflow/runs/:runId", handleWorkspace(handler.Get))
		workspaceScoped.GET("/workflow/runs/:runId/activations", handleWorkspace(handler.ListActivations))
		workspaceScoped.GET("/workflow/runs/:runId/effects", handleWorkspace(handler.ListEffects))
		workspaceScoped.GET("/workflow/runs/:runId/events", handleWorkspace(handler.ListEvents))
		workspaceScoped.GET("/workflow/runs/:runId/artifacts/read", handleWorkspace(handler.ReadArtifact))
		workspaceScoped.POST("/workflow/runs/:runId/cancel", handleCancel(handler.Cancel))
	}
}
