package binding

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
}

func handleWorkspaceJSON[T any](handler func(api.WorkspaceScopedJSON[T]) (api.Response, error)) gin.HandlerFunc {
	return api.HandleWorkspaceScoped(func(request api.WorkspaceScopedRequest) (api.Response, error) {
		body, err := decodeWorkflowBindingJSON[T](request.Gin)
		if err != nil {
			return api.Response{}, err
		}
		return handler(api.WorkspaceScopedJSON[T]{WorkspaceScopedRequest: request, Body: body})
	}, api.WithErrorClassifier(classifyError))
}

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

// RegisterRoutes mounts the human workspace Binding lifecycle. Agent Runtime
// transport is intentionally a separate adapter so model calls cannot pass
// human identity or owner fields through this browser surface.
func RegisterRoutes(router gin.IRouter, dependencies Dependencies) {
	if router == nil || dependencies.Service == nil {
		return
	}
	workspaceScoped := router.Group(
		"/api/v1/workspaces/:workspaceId",
		api.RequireAuthenticatedUser(dependencies.AuthStore),
		api.RequireVerifiedIdentity(dependencies.EmailVerificationRequired),
		api.RequireRouteWorkspace(dependencies.WorkspaceStore),
	)
	handlers := newRouteHandlers(dependencies.Service)

	workspaceScoped.GET("/workflow/bindings", handleWorkspace(handlers.collection.List))
	workspaceScoped.POST("/workflow/bindings", handleWorkspaceJSON[dto.WorkflowBindingCreateRequest](handlers.collection.Create))
	workspaceScoped.POST("/workflow/bindings:validate", handleWorkspaceJSON[dto.WorkflowBindingValidateRequest](handlers.validation.Validate))

	workspaceScoped.GET("/workflow/bindings/:bindingId", handleWorkspace(handlers.detail.Get))
	workspaceScoped.PATCH("/workflow/bindings/:bindingId", handleWorkspaceJSON[dto.WorkflowBindingUpdateRequest](handlers.detail.Update))
	workspaceScoped.POST("/workflow/bindings/:bindingId/disable", handleWorkspace(handlers.detail.Disable))
	workspaceScoped.POST("/workflow/bindings/:bindingId/archive", handleWorkspace(handlers.detail.Archive))
	workspaceScoped.POST("/workflow/bindings/:bindingId/restore", handleWorkspace(handlers.detail.Restore))

	workspaceScoped.POST("/workflow/bindings/:bindingId/revisions", handleWorkspaceJSON[dto.WorkflowBindingRevisionCreateRequest](handlers.revisions.Create))
	workspaceScoped.GET("/workflow/bindings/:bindingId/revisions", handleWorkspace(handlers.revisions.List))
	workspaceScoped.GET("/workflow/bindings/:bindingId/revisions/:revision", handleWorkspace(handlers.revisions.Get))
	workspaceScoped.POST("/workflow/bindings/:bindingId/revisions/:revision/activate", handleWorkspace(handlers.revisions.Activate))
}
