// Package httpx provides the HTTP transport layer: a Chi-based router
// skeleton and Google API style JSON response helpers (WriteJSON,
// WriteError). It deliberately uses package name "httpx" to avoid
// shadowing the standard library "net/http" package at call sites.
package httpx

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

	"github.com/yan1h/agent-coding-workflow/internal/infra/errs"
)

// WriteJSON writes body as JSON with the given HTTP status. The
// Content-Type header is set to application/json before WriteHeader is
// called. Encode errors are intentionally ignored: by the time the
// status has been written the connection is committed, and the caller
// has no meaningful recovery path.
func WriteJSON(w http.ResponseWriter, status int, body any) {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.WriteHeader(status)
	_ = json.NewEncoder(w).Encode(body)
}

// errorResponse is the Google API style flat error body.
type errorResponse struct {
	Code      string         `json:"code"`
	Message   string         `json:"message"`
	Fields    map[string]any `json:"fields,omitempty"`
	RequestID string         `json:"request_id,omitempty"`
}

// WriteError translates err into a JSON error response. *errs.AppError
// values are rendered with their declared Code/Message/Fields and the
// HTTP status mapped via errs.HTTPStatus. Any other error is reported
// as a generic 500 internal error so internal details don't leak.
func WriteError(w http.ResponseWriter, requestID string, err error) {
	if ae, ok := errs.As(err); ok {
		WriteJSON(w, errs.HTTPStatus(ae.Code), errorResponse{
			Code:      string(ae.Code),
			Message:   ae.Message,
			Fields:    ae.Fields,
			RequestID: requestID,
		})
		return
	}
	WriteJSON(w, http.StatusInternalServerError, errorResponse{
		Code:      string(errs.CodeInternal),
		Message:   "internal server error",
		RequestID: requestID,
	})
}
