package httpapi

import (
	"context"
	"encoding/json"

	"github.com/dtoro/oikos/internal/httpapi/gen"
	"github.com/google/uuid"
)

// ─── Classifications ───────────────────────────────────────────────────

func (s *Server) ListClassifications(ctx context.Context, req gen.ListClassificationsRequestObject) (gen.ListClassificationsResponseObject, error) {
	limit := clampLimit(req.Params.Limit)
	var route *string
	if req.Params.Route != nil {
		r := string(*req.Params.Route)
		route = &r
	}
	rows, err := s.pool.Query(ctx, `
		SELECT c.entity_id, c.signal_entity_id, c.target_entity_id, c.action,
		       c.recommended_action, c.risk_class, c.route, c.blast_radius,
		       c.pattern_confidence, c.skill_id, c.autonomy_check, c.reasoning,
		       c.correlation_id, c.created_at,
		       e.slug, COALESCE(se.slug, '') AS signal_slug, COALESCE(te.slug, '') AS target_slug
		FROM classifications c
		LEFT JOIN entities e ON e.id = c.entity_id
		LEFT JOIN entities se ON se.id = c.signal_entity_id
		LEFT JOIN entities te ON te.id = c.target_entity_id
		WHERE ($1::text IS NULL OR c.route = $1)
		  AND ($2::text IS NULL OR e.slug > $2)
		ORDER BY e.slug
		LIMIT $3`,
		route, req.Params.Cursor, limit+1)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	items := []gen.Classification{}
	for rows.Next() {
		var cls gen.Classification
		var recActionJSON []byte
		var reasoningJSON []byte
		var blastRadius []uuid.UUID
		var signalSlug, targetSlug string
		if err := rows.Scan(&cls.Id, &cls.SignalId, &targetSlug, &cls.Action,
			&recActionJSON, &cls.RiskClass, &cls.Route, &blastRadius,
			&cls.PatternConfidence, &cls.SkillId, &cls.AutonomyCheck, &reasoningJSON,
			&cls.CorrelationId, &cls.CreatedAt,
			&cls.Target, &signalSlug, &targetSlug); err != nil {
			return nil, err
		}
		if targetSlug != "" {
			cls.Target = &targetSlug
		}
		var reasoning map[string]any
		if json.Unmarshal(reasoningJSON, &reasoning) == nil {
			cls.Reasoning = reasoning
		}
		if len(blastRadius) > 0 {
			br := make([]string, len(blastRadius))
			for i, id := range blastRadius {
				br[i] = id.String()
			}
			cls.BlastRadius = &br
		}
		items = append(items, cls)
	}
	if rows.Err() != nil {
		return nil, rows.Err()
	}

	var next *string
	if len(items) > limit {
		items = items[:limit]
		if items[len(items)-1].Target != nil {
			next = items[len(items)-1].Target
		}
	}
	if items == nil {
		items = []gen.Classification{}
	}
	return gen.ListClassifications200JSONResponse{Items: items, NextCursor: next}, nil
}
