package outbox

import (
	"errors"
	"net/http"
	"strconv"
	"strings"

	"aigateway.local/core/internal/identity"
	"aigateway.local/core/internal/platform/apiresponse"
	"github.com/jackc/pgx/v5/pgtype"
)

type AdminHTTPHandler struct {
	store    *Store
	identity *identity.Service
	mux      *http.ServeMux
}

func NewAdminHTTPHandler(store *Store, identityService *identity.Service) *AdminHTTPHandler {
	h := &AdminHTTPHandler{store: store, identity: identityService, mux: http.NewServeMux()}
	h.mux.HandleFunc("GET /api/v1/admin/outbox-events", h.list)
	h.mux.HandleFunc("POST /api/v1/admin/outbox-events/{event_id}/retry", h.retry)
	return h
}

func (h *AdminHTTPHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
	h.mux.ServeHTTP(writer, request)
}

func (h *AdminHTTPHandler) list(writer http.ResponseWriter, request *http.Request) {
	if !h.requirePermission(writer, request, identity.PermissionOutboxRead) {
		return
	}
	status := strings.TrimSpace(request.URL.Query().Get("status"))
	if status != "" && status != "pending" && status != "dead" && status != "processed" {
		apiresponse.Error(writer, http.StatusBadRequest, "status 必须是 pending、dead 或 processed")
		return
	}
	limit := 100
	if value := request.URL.Query().Get("limit"); value != "" {
		parsed, err := strconv.Atoi(value)
		if err != nil || parsed < 1 || parsed > 500 {
			apiresponse.Error(writer, http.StatusBadRequest, "limit 必须在 1 到 500 之间")
			return
		}
		limit = parsed
	}
	items, err := h.store.List(request.Context(), status, strings.TrimSpace(request.URL.Query().Get("type")), limit)
	if err != nil {
		apiresponse.Error(writer, http.StatusServiceUnavailable, "事件投递查询服务暂不可用")
		return
	}
	apiresponse.OK(writer, items)
}

func (h *AdminHTTPHandler) retry(writer http.ResponseWriter, request *http.Request) {
	if !h.requirePermission(writer, request, identity.PermissionOutboxManage) {
		return
	}
	eventID := strings.TrimSpace(request.PathValue("event_id"))
	var parsedID pgtype.UUID
	if err := parsedID.Scan(eventID); err != nil || !parsedID.Valid {
		apiresponse.Error(writer, http.StatusBadRequest, "event_id 必须是有效 UUID")
		return
	}
	if err := h.store.Retry(request.Context(), eventID); err != nil {
		if errors.Is(err, ErrEventNotFound) {
			apiresponse.Error(writer, http.StatusNotFound, "待处理或死信事件不存在")
			return
		}
		apiresponse.Error(writer, http.StatusServiceUnavailable, "事件重试服务暂不可用")
		return
	}
	apiresponse.OK(writer, map[string]bool{"retried": true})
}

func (h *AdminHTTPHandler) requirePermission(writer http.ResponseWriter, request *http.Request, permission string) bool {
	account, err := h.identity.Authenticate(request.Context(), identity.KindAdmin, request.Header.Get("Authorization"))
	if err != nil {
		if errors.Is(err, identity.ErrInvalidSession) || errors.Is(err, identity.ErrNotFound) {
			apiresponse.Error(writer, http.StatusUnauthorized, "登录状态无效或已过期")
		} else if errors.Is(err, identity.ErrAccountDisabled) {
			apiresponse.Error(writer, http.StatusForbidden, "管理员账号已被停用")
		} else {
			apiresponse.Error(writer, http.StatusServiceUnavailable, "身份服务暂不可用")
		}
		return false
	}
	if !identity.HasPermission(account, permission) {
		apiresponse.Error(writer, http.StatusForbidden, "缺少事件投递操作权限")
		return false
	}
	return true
}
