package agent

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

	"github.com/gin-gonic/gin"
)

type agentThreadUpstreamRequest struct {
	agentThreadAttestationRequest
	Method string          `json:"method"`
	Path   string          `json:"path"`
	Body   json.RawMessage `json:"body"`
}

func (h *AgentThreadHandler) forwardAgentThreadUpstream(c *gin.Context) {
	request, ok := bindAgentThreadUpstreamRequest(c)
	if !ok {
		return
	}
	attestation, ok := h.resolveAgentThreadAttestation(c, request.target())
	if !ok {
		return
	}
	if h.gateway == nil {
		writeAgentThreadErrorResponse(c, http.StatusServiceUnavailable, "meshx_upstream_unavailable", "agent thread gateway is not configured", agentThreadStageMeshXUpstream)
		return
	}
	result, err := h.gateway.ForwardAgentThreadUpstream(c.Request.Context(), attestation, request.Method, request.Path, request.Body)
	if err != nil {
		writeAgentThreadError(c, agentThreadStageMeshXUpstream, err)
		return
	}
	writeRawJSON(c, result)
}

func bindAgentThreadUpstreamRequest(c *gin.Context) (agentThreadUpstreamRequest, bool) {
	var request agentThreadUpstreamRequest
	if err := c.ShouldBindJSON(&request); err != nil {
		writeAgentThreadError(c, agentThreadStageRequestValidation, badRequest("invalid request body"))
		return agentThreadUpstreamRequest{}, false
	}
	if strings.TrimSpace(request.Path) == "" {
		err := badRequest("path is required")
		writeAgentThreadError(c, agentThreadStageRequestValidation, err)
		return agentThreadUpstreamRequest{}, false
	}
	if len(bytes.TrimSpace(request.Body)) == 0 || bytes.Equal(bytes.TrimSpace(request.Body), []byte("null")) {
		request.Body = json.RawMessage(`{}`)
	}
	return request, true
}

func writeRawJSON(c *gin.Context, payload json.RawMessage) {
	payload = bytes.TrimSpace(payload)
	if len(payload) == 0 {
		payload = []byte("{}")
	}
	c.Data(http.StatusOK, "application/json; charset=utf-8", payload)
}
