package main

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"log/slog"
	"os"

	"github.com/tidbcloud/AgentTeam/internal/api/im"
	"github.com/tidbcloud/AgentTeam/internal/api/llm"
	"github.com/tidbcloud/AgentTeam/internal/apr/runtime"
	"github.com/tidbcloud/AgentTeam/internal/router"
	"github.com/tidbcloud/AgentTeam/internal/store/agent"
	"github.com/tidbcloud/AgentTeam/internal/store/workspace"
	"github.com/tidbcloud/AgentTeam/internal/workflow/bindingmanage"
	"github.com/tidbcloud/AgentTeam/internal/workflow/invocationmanage"
	"github.com/tidbcloud/AgentTeam/internal/workflow/orchestrator"
	"github.com/tidbcloud/AgentTeam/internal/workflow/planmanage"
	"github.com/tidbcloud/AgentTeam/internal/workflow/runmanage"
)

type routeContractDocument struct {
	Version int                        `json:"version"`
	Routes  []router.EdgeRouteContract `json:"routes"`
}

func main() {
	if err := run(os.Stdout); err != nil {
		fmt.Fprintf(os.Stderr, "agentteam-route-contract: %v\n", err)
		os.Exit(1)
	}
}

func run(output io.Writer) error {
	logger := slog.New(slog.NewTextHandler(io.Discard, nil))
	liveEmitter := im.NewLiveEventEmitter(im.NewStreamEventHub(), nil, logger)

	centralRouter := router.NewRouterForProfile(router.ProfileCentral, router.Dependencies{Logger: logger})
	workspaceDependencies := router.Dependencies{
		Logger:      logger,
		LiveEmitter: liveEmitter,
		API: router.APIDependencies{
			LLM: llm.Dependencies{APRDispatcher: runtime.NewDispatcher()},
		},
	}
	installWorkflowRouteContractDependencies(&workspaceDependencies)
	workspaceRouter := router.NewRouterForProfile(router.ProfileWorkspace, workspaceDependencies)
	contract, err := router.BuildEdgeRouteContractForRouters(centralRouter, workspaceRouter)
	if err != nil {
		return err
	}

	encoder := json.NewEncoder(output)
	encoder.SetIndent("", "  ")
	return encoder.Encode(routeContractDocument{
		Version: 1,
		Routes:  contract,
	})
}

// installWorkflowRouteContractDependencies supplies non-operational service
// and trust-boundary implementations solely so dependency-gated routes are
// visible to route inventory generation. The contract builder never serves a
// request, so these collaborators intentionally fail if invoked.
func installWorkflowRouteContractDependencies(dependencies *router.Dependencies) {
	if dependencies == nil {
		return
	}
	plans := planmanage.New(nil)
	bindings := bindingmanage.New(nil, nil)
	invocations := invocationmanage.New(nil)
	runs := runmanage.New(nil)
	trust := routeContractInertWorkflowTrust{}

	dependencies.API.WorkflowPlan.Service = plans
	dependencies.API.WorkflowBinding.Service = bindings
	dependencies.API.WorkflowInvocation.Service = invocations
	dependencies.API.WorkflowRun.Service = runs
	dependencies.Agent.Auth = trust
	dependencies.Agent.WorkflowPlans = plans
	dependencies.Agent.WorkflowBindings = bindings
	dependencies.Agent.WorkflowBindingOwners = trust
	dependencies.Agent.WorkflowBindingWorkspace = trust
	dependencies.Agent.WorkflowInvocations = invocations
	dependencies.Agent.WorkflowInvocationOwners = trust
	dependencies.Agent.WorkflowInvocationWorkspace = trust
	dependencies.Agent.WorkflowRuns = runs
	dependencies.Agent.WorkflowRunCallbacks = routeContractInertWorkflowCallbacks{}
}

type routeContractInertWorkflowTrust struct{}
type routeContractInertWorkflowCallbacks struct{}

func (routeContractInertWorkflowCallbacks) ExecuteCallback(context.Context, orchestrator.CallbackCommand) (orchestrator.CallbackResult, error) {
	return orchestrator.CallbackResult{}, fmt.Errorf("route contract dependency is inert")
}

func (routeContractInertWorkflowCallbacks) ListCallbacks(context.Context, orchestrator.CallbackListCommand) (orchestrator.CallbackListResult, error) {
	return orchestrator.CallbackListResult{}, fmt.Errorf("route contract dependency is inert")
}

func (routeContractInertWorkflowTrust) AuthenticateAgent(context.Context, string, string) (agent.AuthenticatedAgent, error) {
	return agent.AuthenticatedAgent{}, fmt.Errorf("route contract dependency is inert")
}

func (routeContractInertWorkflowTrust) AgentManagedByUser(context.Context, string, string) (string, error) {
	return "", fmt.Errorf("route contract dependency is inert")
}

func (routeContractInertWorkflowTrust) GetWorkspaceForUser(context.Context, string, string) (workspace.Summary, error) {
	return workspace.Summary{}, fmt.Errorf("route contract dependency is inert")
}
