package admin

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

	"github.com/go-chi/chi/v5"

	"github.com/veylant/ia-gateway/internal/apierror"
	"github.com/veylant/ia-gateway/internal/flags"
)

// ─── Feature flags admin API (E11-07) ────────────────────────────────────────
//
// Routes (mounted under /v1/admin):
//   GET    /flags           → list all flags for the tenant + global defaults
//   PUT    /flags/{name}    → upsert a flag (create or update)
//   DELETE /flags/{name}    → delete a tenant-scoped flag

// upsertFlagRequest is the JSON body for PUT /flags/{name}.
type upsertFlagRequest struct {
	Enabled bool `json:"enabled"`
}

// flagNotEnabled writes a 501 if the flag store is not configured.
func (h *Handler) flagNotEnabled(w http.ResponseWriter) bool {
	if h.flagStore == nil {
		apierror.WriteError(w, &apierror.APIError{
			Type:       "not_implemented",
			Message:    "feature flag store not enabled",
			HTTPStatus: http.StatusNotImplemented,
		})
		return true
	}
	return false
}

// listFlags handles GET /v1/admin/flags.
// Returns all flags scoped to the caller's tenant plus global (tenant_id="") flags.
func (h *Handler) listFlags(w http.ResponseWriter, r *http.Request) {
	if h.flagNotEnabled(w) {
		return
	}
	tenantID, ok := tenantFromCtx(w, r)
	if !ok {
		return
	}

	list, err := h.flagStore.List(r.Context(), tenantID)
	if err != nil {
		apierror.WriteError(w, apierror.NewUpstreamError("failed to list flags: "+err.Error()))
		return
	}
	if list == nil {
		list = []flags.FeatureFlag{}
	}
	writeJSON(w, http.StatusOK, map[string]interface{}{"data": list})
}

// upsertFlag handles PUT /v1/admin/flags/{name}.
// Creates or updates the flag for the caller's tenant. The flag name is taken
// from the URL; global flags (tenant_id="") cannot be modified via this endpoint.
func (h *Handler) upsertFlag(w http.ResponseWriter, r *http.Request) {
	if h.flagNotEnabled(w) {
		return
	}
	tenantID, ok := tenantFromCtx(w, r)
	if !ok {
		return
	}
	name := chi.URLParam(r, "name")
	if name == "" {
		apierror.WriteError(w, apierror.NewBadRequestError("flag name is required"))
		return
	}

	var req upsertFlagRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		apierror.WriteError(w, apierror.NewBadRequestError("invalid JSON: "+err.Error()))
		return
	}

	f, err := h.flagStore.Set(r.Context(), tenantID, name, req.Enabled)
	if err != nil {
		apierror.WriteError(w, apierror.NewUpstreamError("failed to set flag: "+err.Error()))
		return
	}
	writeJSON(w, http.StatusOK, f)
}

// deleteFlag handles DELETE /v1/admin/flags/{name}.
// Removes the tenant-scoped flag. Returns 404 if the flag does not exist.
// Global flags (tenant_id="") are not deleted by this endpoint.
func (h *Handler) deleteFlag(w http.ResponseWriter, r *http.Request) {
	if h.flagNotEnabled(w) {
		return
	}
	tenantID, ok := tenantFromCtx(w, r)
	if !ok {
		return
	}
	name := chi.URLParam(r, "name")
	if name == "" {
		apierror.WriteError(w, apierror.NewBadRequestError("flag name is required"))
		return
	}

	err := h.flagStore.Delete(r.Context(), tenantID, name)
	if err == flags.ErrNotFound {
		apierror.WriteError(w, &apierror.APIError{
			Type:       "not_found_error",
			Message:    "feature flag not found",
			HTTPStatus: http.StatusNotFound,
		})
		return
	}
	if err != nil {
		apierror.WriteError(w, apierror.NewUpstreamError("failed to delete flag: "+err.Error()))
		return
	}
	w.WriteHeader(http.StatusNoContent)
}
