package internal

import (
	"log"
	"net/http"
	"time"

	"github.com/go-chi/chi/v5"
	"github.com/go-chi/chi/v5/middleware"
	"github.com/go-chi/cors"
	"github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
	EnableCompression: true,
	HandshakeTimeout:  time.Second * 2,
}

type adminHandler struct {
	Cache
	Storage
	EventSubscriber
	EventPublisher
	*RuleEngine
	h http.Handler
}

func NewAdminHandler(c Cache, s Storage, re *RuleEngine) http.Handler {
	handler := chi.NewRouter()

	a := &adminHandler{
		Cache:      c,
		Storage:    s,
		RuleEngine: re,
		h:          handler,
	}

	handler.Use(middleware.RequestID)
	handler.Use(middleware.RealIP)
	handler.Use(middleware.Logger)
	handler.Use(middleware.AllowContentType("application/json; utf-8", "application/json"))
	handler.Use(middleware.Timeout(time.Second * 5))

	handler.Use(cors.Handler(cors.Options{
		AllowedOrigins:   []string{"http://*", "https://*"},
		AllowedMethods:   []string{"GET", "PUT", "DELETE", "POST", "OPTIONS"},
		AllowedHeaders:   []string{"Content-Type", "Accept"},
		AllowCredentials: false,
		MaxAge:           300,
	}))

	handler.Use(middleware.Recoverer)

	handler.Route("/api/v1", func(r chi.Router) {
		r.Get("/metrics/log", RestHandler(a.getLog).ToHF())
		r.Get("/metrics/stats", RestHandler(a.getStats).ToHF())

		r.Put("/rules", RestHandler(a.createRule).ToHF())
		r.Get("/rules", RestHandler(a.getRules).ToHF())
		r.Get("/rules/{id:[0-9]+}", RestHandler(a.getRule).ToHF())
		r.Post("/rules/{id:[0-9]+}", RestHandler(a.updateRule).ToHF())
		r.Delete("/rules/{id:[0-9]+}", RestHandler(a.deleteRule).ToHF())

		r.Put("/recursors", RestHandler(a.addRecursor).ToHF())
		r.Get("/recursors", RestHandler(a.getRecursors).ToHF())
		r.Get("/recursors/{id:[0-9]+}", RestHandler(a.getRecursor).ToHF())
		r.Delete("/recursor/{id:[0-9]+}", RestHandler(a.deleteRecursor).ToHF())

		// r.Put("/rules/lists", a.addRulelist)
		// r.Get("/rules/lists", a.getRuleLists)
		// r.Post("/rules/lists/reload/{id}", a.reloadRuleLists)
		// r.Delete("/rules/lists/{id}", a.deleteRuleList)

		// r.Get("/updates", RestHandler(a.getStats).ToHF())
		// r.Delete("/cache/purgeall", RestHandler(a.purgeAll).ToHF())
		// r.Delete("/cache/purge", a.purgeKey)
		// r.Get("/cache", a.getCacheContents)
		r.HandleFunc("/signal", a.signal)
	})

	return a
}

func (a *adminHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	a.h.ServeHTTP(w, r)
}

func (a *adminHandler) signal(w http.ResponseWriter, r *http.Request) {
	c, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Print("could not upgrade to a websocket:", err)
		return
	}

	defer c.Close()
	for {

		// send any updates that come through to the client
	}
}
