// Package machine owns Desktop-only Machine setup orchestration.
package machine

import (
	"context"

	"github.com/gin-gonic/gin"

	"github.com/tidbcloud/AgentTeam/desktop/internal/api/session"
	"github.com/tidbcloud/AgentTeam/desktop/internal/diagnosticbundle"
	"github.com/tidbcloud/AgentTeam/desktop/internal/metrics"
	"github.com/tidbcloud/AgentTeam/desktop/internal/profile"
	"github.com/tidbcloud/AgentTeam/desktop/internal/uisession"
	"github.com/tidbcloud/AgentTeam/desktop/internal/userauth"
)

type Dependencies struct {
	Auth                *userauth.Manager
	Agents              *profile.AgentManager
	ConnectionReadiness ConnectionReadiness
	DashboardMetrics    DashboardMetrics
	TokenTracking       metrics.TokenSourceQuerier
	DiagnosticPaths     diagnosticbundle.Paths
	Service             *Service
	Servers             *profile.ServerManager
	Sessions            *uisession.Store
	AgentSessions       session.SessionsStore
}

type ConnectionReadiness interface {
	WaitForServerConnection(context.Context, string) error
}

func NewService(dependencies Dependencies) *Service {
	return &Service{
		auth:                dependencies.Auth,
		agents:              dependencies.Agents,
		connectionReadiness: dependencies.ConnectionReadiness,
		diagnosticPaths:     dependencies.DiagnosticPaths,
		servers:             dependencies.Servers,
	}
}

func RegisterRoutes(routes gin.IRoutes, dependencies Dependencies) {
	service := dependencies.Service
	if service == nil {
		service = NewService(dependencies)
	}
	handler := &Handler{
		service:          service,
		sessions:         dependencies.Sessions,
		agentSessions:    dependencies.AgentSessions,
		dashboardMetrics: dependencies.DashboardMetrics,
		tokenTracking:    dependencies.TokenTracking,
	}
	routes.GET("/machines/current-binding", handler.GetCurrentBinding)
	routes.POST("/machines/current-bindings", handler.CreateCurrentBinding)
	routes.POST("/machines/current-bindings/restore", handler.RestoreCurrentBinding)
	routes.GET("/bundles/machines/:machineId/dashboard", handler.GetDashboard)
}

// RegisterDiagnosticDownloadRoute registers the renderer-resource download
// separately from ordinary /api/internal routes because browser navigation
// cannot attach the Authorization header used by the local API transport.
func RegisterDiagnosticDownloadRoute(routes gin.IRoutes, dependencies Dependencies) {
	service := dependencies.Service
	if service == nil {
		service = NewService(dependencies)
	}
	handler := &Handler{
		service:  service,
		sessions: dependencies.Sessions,
	}
	routes.GET(
		"/api/internal/machines/:machineId/diagnostics/archive",
		diagnosticDownloadSession(),
		handler.DownloadDiagnostics,
	)
}

type DashboardMetrics interface {
	QueryAgentsDashboard([]string, metrics.TimeWindow) metrics.AgentDashboardMetrics
}
