package routes

import (
	"log"
	"net/http"
	"strings"

	"abuse_registration_poc/internal/handlers"
	"abuse_registration_poc/internal/middlewares"
	"abuse_registration_poc/internal/web"
)

func RegisterRoutes(h *handlers.Handler) http.Handler {
	mux := http.NewServeMux()

	mux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
		if (request.Method == http.MethodGet || request.Method == http.MethodHead) && request.URL.Path == "/" {
			h.Index(writer, request)
			return
		}
		if strings.HasPrefix(request.URL.Path, "/api/") {
			handlers.WriteJSON(writer, http.StatusNotFound, map[string]string{"message": "Not found."})
			return
		}
		handlers.WriteText(writer, http.StatusNotFound, "Not found. This POC only serves /, /login, /health, /demo/registrations, and /api/v1/...\n")
	})

	mux.HandleFunc("/health", method(http.MethodGet, h.Health))
	mux.HandleFunc("/login", method(http.MethodPost, h.Login))
	mux.HandleFunc("/demo/registrations", method(http.MethodGet, h.DemoRegistrations))
	staticFS, err := web.StaticFS()
	if err != nil {
		log.Fatalf("failed to initialize embedded static assets: %v", err)
	}
	mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(staticFS))))
	mux.HandleFunc("/favicon.ico", func(writer http.ResponseWriter, request *http.Request) {
		favicon, err := web.Favicon()
		if err != nil {
			handlers.WriteText(writer, http.StatusNotFound, "Not found.\n")
			return
		}
		writer.Header().Set("Content-Type", "image/x-icon")
		_, _ = writer.Write(favicon)
	})

	mux.Handle("/api/v1/categories", middlewares.Protected("/api/v1/categories", http.HandlerFunc(method(http.MethodGet, h.Categories))))
	mux.Handle("/api/v1/locations", middlewares.Protected("/api/v1/locations", http.HandlerFunc(method(http.MethodGet, h.Locations))))
	mux.Handle("/api/v1/reset", middlewares.Protected("/api/v1/reset", http.HandlerFunc(method(http.MethodPost, h.ResetRegistrations))))
	mux.Handle("/api/v1/registrations", middlewares.Protected("/api/v1/registrations", http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
		switch request.Method {
		case http.MethodGet:
			h.ListRegistrations(writer, request)
		case http.MethodPost:
			h.CreateRegistration(writer, request)
		default:
			methodNotAllowed(writer)
		}
	})))
	mux.Handle("/api/v1/registrations/", middlewares.Protected("/api/v1/registrations/:id", http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
		id := strings.TrimPrefix(request.URL.Path, "/api/v1/registrations/")
		if id == "" || strings.Contains(id, "/") {
			handlers.WriteJSON(writer, http.StatusNotFound, map[string]string{"message": "Not found."})
			return
		}
		switch request.Method {
		case http.MethodGet:
			h.GetRegistration(writer, request, id)
		case http.MethodPut:
			h.UpdateRegistration(writer, request, id)
		case http.MethodDelete:
			h.DeleteRegistration(writer, request, id)
		default:
			methodNotAllowed(writer)
		}
	})))

	return middlewares.CORS(mux)
}

func method(expected string, handler http.HandlerFunc) http.HandlerFunc {
	return func(writer http.ResponseWriter, request *http.Request) {
		if request.Method != expected {
			methodNotAllowed(writer)
			return
		}
		handler(writer, request)
	}
}

func methodNotAllowed(writer http.ResponseWriter) {
	handlers.WriteJSON(writer, http.StatusMethodNotAllowed, map[string]string{"message": "Method not allowed."})
}
