package pii

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

	"go.uber.org/zap"

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

// AnalyzeRequest is the JSON body accepted by POST /v1/pii/analyze.
type AnalyzeRequest struct {
	Text string `json:"text"`
}

// AnalyzeEntity is a single PII entity returned by the analyze endpoint.
type AnalyzeEntity struct {
	Type       string  `json:"type"`
	Start      int     `json:"start"`
	End        int     `json:"end"`
	Confidence float64 `json:"confidence"`
	Layer      string  `json:"layer"`
}

// AnalyzeResponse is the JSON response of POST /v1/pii/analyze.
type AnalyzeResponse struct {
	Anonymized string          `json:"anonymized"`
	Entities   []AnalyzeEntity `json:"entities"`
}

// AnalyzeHandler wraps a pii.Client as an HTTP handler for the playground.
// It is safe to call when client is nil: returns the original text unchanged.
type AnalyzeHandler struct {
	client *Client
	logger *zap.Logger
}

// NewAnalyzeHandler creates a new AnalyzeHandler.
// client may be nil (PII service disabled) — the handler degrades gracefully.
func NewAnalyzeHandler(client *Client, logger *zap.Logger) *AnalyzeHandler {
	return &AnalyzeHandler{client: client, logger: logger}
}

func (h *AnalyzeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var req AnalyzeRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		apierror.WriteError(w, apierror.NewBadRequestError("invalid JSON: "+err.Error()))
		return
	}
	if req.Text == "" {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		_ = json.NewEncoder(w).Encode(AnalyzeResponse{Anonymized: "", Entities: []AnalyzeEntity{}})
		return
	}

	// PII service disabled — return text unchanged.
	if h.client == nil {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		_ = json.NewEncoder(w).Encode(AnalyzeResponse{
			Anonymized: req.Text,
			Entities:   []AnalyzeEntity{},
		})
		return
	}

	resp, err := h.client.Detect(r.Context(), req.Text, "playground", "playground-analyze", true, false)
	if err != nil {
		h.logger.Warn("PII analyze failed", zap.Error(err))
		// Fail-open: return text unchanged rather than erroring.
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		_ = json.NewEncoder(w).Encode(AnalyzeResponse{
			Anonymized: req.Text,
			Entities:   []AnalyzeEntity{},
		})
		return
	}

	entities := make([]AnalyzeEntity, 0, len(resp.Entities))
	for _, e := range resp.Entities {
		entities = append(entities, AnalyzeEntity{
			Type:       e.EntityType,
			Start:      int(e.Start),
			End:        int(e.End),
			Confidence: float64(e.Confidence),
			Layer:      e.DetectionLayer,
		})
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	_ = json.NewEncoder(w).Encode(AnalyzeResponse{
		Anonymized: resp.AnonymizedText,
		Entities:   entities,
	})
}
