package router

import (
	"net/http"
	"time"

	"github.com/CubeCraft-Creations/Extrudex/backend/internal/config"
	"github.com/CubeCraft-Creations/Extrudex/backend/internal/handlers"
	"github.com/CubeCraft-Creations/Extrudex/backend/internal/repositories"
	"github.com/CubeCraft-Creations/Extrudex/backend/internal/services"
	"github.com/CubeCraft-Creations/Extrudex/backend/internal/sse"
	"github.com/go-chi/chi/v5"
	"github.com/go-chi/chi/v5/middleware"
	"github.com/jackc/pgx/v5/pgxpool"
)

// New creates and configures a Chi router with all middleware and handlers mounted.
func New(cfg *config.Config, dbPool *pgxpool.Pool, sseBC *sse.Broadcaster) chi.Router {
	r := chi.NewRouter()

	// Middleware
	r.Use(middleware.RequestID)
	r.Use(middleware.RealIP)
	r.Use(middleware.Logger)
	r.Use(middleware.Recoverer)
	// Timeout middleware is applied per-route below to exclude SSE

	// CORS
	r.Use(func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Access-Control-Allow-Origin", cfg.CorsOrigin)
			w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
			w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
			if r.Method == http.MethodOptions {
				w.WriteHeader(http.StatusNoContent)
				return
			}
			next.ServeHTTP(w, r)
		})
	})

	// Health check (with timeout)
	healthHandler := handlers.NewHealthHandler(dbPool)
	r.With(middleware.Timeout(30 * time.Second)).Get("/health", healthHandler.ServeHTTP)

	// ── Repositories ──────────────────────────────────────────────────────
	materialRepo := repositories.NewMaterialRepository(dbPool)
	filamentRepo := repositories.NewFilamentRepository(dbPool)
	printerRepo := repositories.NewPrinterRepository(dbPool)
	printJobRepo := repositories.NewPrintJobRepository(dbPool)
	usageLogRepo := repositories.NewUsageLogRepository(dbPool)

	// ── Services ──────────────────────────────────────────────────────────
	filamentService := services.NewFilamentService(filamentRepo)
	printerService := services.NewPrinterService(printerRepo)
	printJobService := services.NewPrintJobService(printJobRepo)

	// ── Handlers ──────────────────────────────────────────────────────────
	materialHandler := handlers.NewMaterialHandler(materialRepo)
	filamentHandler := handlers.NewFilamentHandler(filamentService)
	printerHandler := handlers.NewPrinterHandler(printerService)
	printJobHandler := handlers.NewPrintJobHandler(printJobService)
	usageLogHandler := handlers.NewUsageLogHandler(usageLogRepo)

	// ── API Routes (with timeout) ─────────────────────────────────────────
	r.Route("/api", func(r chi.Router) {
		r.Use(middleware.Timeout(60 * time.Second))
		r.Get("/materials", materialHandler.List)

		r.Route("/filaments", func(r chi.Router) {
			r.Get("/", filamentHandler.List)
			r.Post("/", filamentHandler.Create)
			r.Route("/{id}", func(r chi.Router) {
				r.Get("/", filamentHandler.Get)
				r.Put("/", filamentHandler.Update)
				r.Delete("/", filamentHandler.Delete)
			})
		})

		r.Get("/printers", printerHandler.List)
		r.Get("/print-jobs", printJobHandler.List)
		r.Get("/usage-logs", usageLogHandler.List)

		// SSE Events stream
		sseHandler := sse.NewHandler(sseBC)
		r.Get("/events", sseHandler.ServeHTTP)
	})

	return r
}
