package main

import (
	"net/http"
	"tercul/internal/adapters/graphql"
	"tercul/internal/observability"
	"tercul/internal/platform/auth"

	"github.com/99designs/gqlgen/graphql/handler"
	"github.com/99designs/gqlgen/graphql/playground"
	"github.com/prometheus/client_golang/prometheus"
)

// NewAPIServer creates a new http.ServeMux and configures it with all the API routes,
// including the GraphQL endpoint, GraphQL Playground, and Prometheus metrics.
func NewAPIServer(
	resolver *graphql.Resolver,
	jwtManager *auth.JWTManager,
	metrics *observability.Metrics,
	logger *observability.Logger,
	reg *prometheus.Registry,
) *http.ServeMux {
	// Configure the GraphQL server
	c := graphql.Config{Resolvers: resolver}
	c.Directives.Binding = graphql.Binding

	// Create the core GraphQL handler
	graphqlHandler := handler.New(graphql.NewExecutableSchema(c))
	graphqlHandler.SetErrorPresenter(graphql.NewErrorPresenter())

	// Create the middleware chain for the GraphQL endpoint.
	// Middlewares are applied from bottom to top.
	var chain http.Handler
	chain = graphqlHandler
	chain = metrics.PrometheusMiddleware(chain)
	chain = observability.LoggingMiddleware(logger)(chain) // Must run after auth and tracing
	chain = auth.GraphQLAuthMiddleware(jwtManager)(chain)
	chain = observability.TracingMiddleware(chain)
	chain = observability.RequestIDMiddleware(chain)

	// Create a new ServeMux and register all handlers
	mux := http.NewServeMux()
	mux.Handle("/query", chain)
	mux.Handle("/playground", playground.Handler("GraphQL Playground", "/query"))
	mux.Handle("/metrics", observability.PrometheusHandler(reg))

	return mux
}
