package spindle

import (
	"crypto/subtle"
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/bluesky-social/indigo/atproto/syntax"
	"github.com/go-chi/chi/v5"
)

type adminReq struct {
	Did string `json:"did"`
}

func (s *Spindle) adminRouter() http.Handler {
	r := chi.NewRouter()
	r.Use(s.adminMiddleware)
	r.Post("/member/allow", s.handleAdminMemberAllow)
	r.Post("/member/block", s.handleAdminMemberBlock)
	return r
}

func (s *Spindle) adminMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		password := s.cfg.Server.AdminPassword
		u, p, ok := r.BasicAuth()
		valid := password != "" &&
			ok &&
			u == "admin" &&
			subtle.ConstantTimeCompare([]byte(p), []byte(password)) == 1
		if !valid {
			http.Error(w, "Unauthorized", http.StatusUnauthorized)
			return
		}
		next.ServeHTTP(w, r)
	})
}

func (s *Spindle) handleAdminMemberAllow(w http.ResponseWriter, r *http.Request) {
	var req adminReq
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "bad request body", http.StatusBadRequest)
		return
	}
	did, err := syntax.ParseDID(req.Did)
	if err != nil {
		http.Error(w, fmt.Sprintf("invalid did: %v", err), http.StatusBadRequest)
		return
	}
	if err := s.AllowMember(r.Context(), did); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

func (s *Spindle) handleAdminMemberBlock(w http.ResponseWriter, r *http.Request) {
	var req adminReq
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "bad request body", http.StatusBadRequest)
		return
	}
	did, err := syntax.ParseDID(req.Did)
	if err != nil {
		http.Error(w, fmt.Sprintf("invalid did: %v", err), http.StatusBadRequest)
		return
	}
	if err := s.BlockMember(r.Context(), did); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}
