package instance

import (
	"encoding/json"
	"net/http"

	"github.com/gorilla/mux"
	log "github.com/sirupsen/logrus"

	nbinstance "github.com/netbirdio/netbird/management/server/instance"
	"github.com/netbirdio/netbird/shared/management/http/api"
	"github.com/netbirdio/netbird/shared/management/http/util"
)

// handler handles the instance setup HTTP endpoints
type handler struct {
	instanceManager nbinstance.Manager
}

// AddEndpoints registers the instance setup endpoints.
// These endpoints bypass authentication for initial setup.
func AddEndpoints(instanceManager nbinstance.Manager, router *mux.Router) {
	h := &handler{
		instanceManager: instanceManager,
	}

	router.HandleFunc("/instance", h.getInstanceStatus).Methods("GET", "OPTIONS")
	router.HandleFunc("/setup", h.setup).Methods("POST", "OPTIONS")
}

// AddVersionEndpoint registers the authenticated version endpoint.
func AddVersionEndpoint(instanceManager nbinstance.Manager, router *mux.Router) {
	h := &handler{
		instanceManager: instanceManager,
	}

	router.HandleFunc("/instance/version", h.getVersionInfo).Methods("GET", "OPTIONS")
}

// getInstanceStatus returns the instance status including whether setup is required.
// This endpoint is unauthenticated.
func (h *handler) getInstanceStatus(w http.ResponseWriter, r *http.Request) {
	setupRequired, err := h.instanceManager.IsSetupRequired(r.Context())
	if err != nil {
		log.WithContext(r.Context()).Errorf("failed to check setup status: %v", err)
		util.WriteErrorResponse("failed to check instance status", http.StatusInternalServerError, w)
		return
	}

	util.WriteJSONObject(r.Context(), w, api.InstanceStatus{
		SetupRequired: setupRequired,
	})
}

// setup creates the initial admin user for the instance.
// This endpoint is unauthenticated but only works when setup is required.
func (h *handler) setup(w http.ResponseWriter, r *http.Request) {
	var req api.SetupRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		util.WriteErrorResponse("invalid request body", http.StatusBadRequest, w)
		return
	}

	userData, err := h.instanceManager.CreateOwnerUser(r.Context(), req.Email, req.Password, req.Name)
	if err != nil {
		util.WriteError(r.Context(), err, w)
		return
	}

	log.WithContext(r.Context()).Infof("instance setup completed: created user %s", req.Email)

	util.WriteJSONObject(r.Context(), w, api.SetupResponse{
		UserId: userData.ID,
		Email:  userData.Email,
	})
}

// getVersionInfo returns version information for NetBird components.
// This endpoint requires authentication.
func (h *handler) getVersionInfo(w http.ResponseWriter, r *http.Request) {
	versionInfo, err := h.instanceManager.GetVersionInfo(r.Context())
	if err != nil {
		log.WithContext(r.Context()).Errorf("failed to get version info: %v", err)
		util.WriteErrorResponse("failed to get version info", http.StatusInternalServerError, w)
		return
	}

	resp := api.InstanceVersionInfo{
		ManagementCurrentVersion:  versionInfo.CurrentVersion,
		ManagementUpdateAvailable: versionInfo.ManagementUpdateAvailable,
	}

	if versionInfo.DashboardVersion != "" {
		resp.DashboardAvailableVersion = &versionInfo.DashboardVersion
	}

	if versionInfo.ManagementVersion != "" {
		resp.ManagementAvailableVersion = &versionInfo.ManagementVersion
	}

	util.WriteJSONObject(r.Context(), w, resp)
}
