package router

import (
	"io/fs"
	"net/http"

	"crowdsec-dashy/internal/config"
	"crowdsec-dashy/internal/crowdsec"
	"crowdsec-dashy/internal/handlers"
	"crowdsec-dashy/internal/middleware"
)

// New constructs the full HTTP handler: renderer, deps, routes, and middleware chain.
func New(cfg *config.Config, lapi *crowdsec.LAPIClient, webFS fs.FS) (http.Handler, error) {
	renderer, err := handlers.NewRenderer(webFS)
	if err != nil {
		return nil, err
	}

	deps := handlers.Deps{
		Renderer:     renderer,
		LAPI:         lapi,
		CLI:          crowdsec.NewCLIClient(cfg.CscliPath),
		CLIAvailable: cfg.CscliAvailable(),
		PollInterval: cfg.PollIntervalSec,
	}

	mux := http.NewServeMux()

	// Static files served from embedded FS sub-tree.
	staticFS, err := fs.Sub(webFS, "static")
	if err != nil {
		return nil, err
	}
	mux.Handle("GET /static/", http.StripPrefix("/static/", http.FileServer(http.FS(staticFS))))

	// Auth (exempt from session check — SessionAuth skips /login internally)
	auth := handlers.NewAuthHandler(renderer, cfg.UISessionSecret, cfg.UIUsername, cfg.VerifyUIPassword)
	mux.HandleFunc("GET /login", auth.Login)
	mux.HandleFunc("POST /login", auth.Login)
	mux.HandleFunc("POST /logout", auth.Logout)

	// Dashboard
	dash := handlers.NewDashboardHandler(deps)
	mux.HandleFunc("GET /{$}", dash.ServeHTTP)

	// Decisions
	dec := handlers.NewDecisionsHandler(deps)
	mux.HandleFunc("GET /decisions", dec.List)
	mux.HandleFunc("POST /decisions/add", dec.Add)
	mux.HandleFunc("POST /decisions/delete", dec.Delete)

	// Alerts
	alrt := handlers.NewAlertsHandler(deps)
	mux.HandleFunc("GET /alerts", alrt.List)
	mux.HandleFunc("POST /alerts/delete", alrt.Delete)

	// Bouncers
	bnc := handlers.NewBouncersHandler(deps)
	mux.HandleFunc("GET /bouncers", bnc.List)
	mux.HandleFunc("POST /bouncers/add", bnc.Add)
	mux.HandleFunc("POST /bouncers/delete", bnc.Delete)

	// Machines
	mch := handlers.NewMachinesHandler(deps)
	mux.HandleFunc("GET /machines", mch.List)
	mux.HandleFunc("POST /machines/delete", mch.Delete)
	mux.HandleFunc("POST /machines/validate", mch.Validate)

	// Hub
	hub := handlers.NewHubHandler(deps)
	mux.HandleFunc("GET /hub", hub.List)
	mux.HandleFunc("POST /hub/install", hub.Install)
	mux.HandleFunc("POST /hub/remove", hub.Remove)
	mux.HandleFunc("POST /hub/update", hub.Update)

	// Metrics
	met := handlers.NewMetricsHandler(deps)
	mux.HandleFunc("GET /metrics-ui", met.ServeHTTP)

	// Internal JSON API
	api := handlers.NewAPIHandler(deps)
	mux.HandleFunc("GET /api/v1/stats", api.Stats)
	mux.HandleFunc("GET /api/v1/health", api.Health)

	chain := middleware.Chain(
		middleware.SessionAuth(cfg.UISessionSecret),
		middleware.Logger(),
		middleware.SecureHeaders(),
		middleware.Recovery(),
	)

	return chain(mux), nil
}
