package httpapi

import (
	"encoding/json"
	"log/slog"
	"net/http"
	"sort"
)

// capabilityTimelineItem summarizes one verb's track record — when the
// agent first succeeded at it, and how reliable it's been since. Derived
// directly from executions (which has real, growing data) rather than the
// patterns/skills tables, which are correctly modeled but have zero writers
// anywhere in the codebase today — building against them now would ship a
// permanently empty page. See plans/2026-07-10-general-gated-execution.md
// step 8 evaluation.
type capabilityTimelineItem struct {
	Verb         string  `json:"verb"`
	FirstSuccess *string `json:"first_success"`
	Successes    int     `json:"successes"`
	Total        int     `json:"total"`
}

// serveLearningTimeline backs the Learning page's capability timeline: one
// row per distinct verb (parsed via splitAction, same helper the activity
// feed uses), ordered by when it first succeeded — an honest "the system
// learned to do X" signal without depending on the unpopulated patterns
// table.
func (s *Server) serveLearningTimeline(w http.ResponseWriter, req *http.Request) {
	ctx := req.Context()
	rows, err := s.pool.Query(ctx, `
		SELECT action, status, created_at::text
		FROM executions
		ORDER BY created_at`)
	if err != nil {
		writeProblem(w, req, http.StatusInternalServerError, "query failed", err.Error())
		return
	}
	defer rows.Close()

	type agg struct {
		firstSuccess *string
		successes    int
		total        int
	}
	byVerb := map[string]*agg{}
	for rows.Next() {
		var action, status, createdAt string
		if err := rows.Scan(&action, &status, &createdAt); err != nil {
			slog.Error("httpapi: learning/timeline row scan failed", "error", err)
			continue
		}
		verb, _ := splitAction(action)
		a, ok := byVerb[verb]
		if !ok {
			a = &agg{}
			byVerb[verb] = a
		}
		a.total++
		if status == "completed" {
			a.successes++
			if a.firstSuccess == nil {
				ca := createdAt
				a.firstSuccess = &ca
			}
		}
	}

	items := make([]capabilityTimelineItem, 0, len(byVerb))
	for verb, a := range byVerb {
		items = append(items, capabilityTimelineItem{
			Verb: verb, FirstSuccess: a.firstSuccess, Successes: a.successes, Total: a.total,
		})
	}
	// Verbs with at least one success sort by when that first happened;
	// verbs that have never succeeded sort last (nothing to celebrate yet).
	sort.Slice(items, func(i, j int) bool {
		fi, fj := items[i].FirstSuccess, items[j].FirstSuccess
		if fi == nil {
			return false
		}
		if fj == nil {
			return true
		}
		return *fi < *fj
	})

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]any{"items": items})
}

type trendBucket struct {
	Day       string `json:"day"`
	Successes int    `json:"successes"`
	Failures  int    `json:"failures"`
}

// serveLearningTrend backs the Learning page's 30-day success/fail trend
// chart — a daily bucket of execution outcomes, straight off the executions
// table.
func (s *Server) serveLearningTrend(w http.ResponseWriter, req *http.Request) {
	ctx := req.Context()
	rows, err := s.pool.Query(ctx, `
		SELECT date_trunc('day', created_at)::date::text AS day,
		       COUNT(*) FILTER (WHERE status = 'completed') AS successes,
		       COUNT(*) FILTER (WHERE status = 'failed') AS failures
		FROM executions
		WHERE created_at > now() - interval '30 days'
		GROUP BY day
		ORDER BY day`)
	if err != nil {
		writeProblem(w, req, http.StatusInternalServerError, "query failed", err.Error())
		return
	}
	defer rows.Close()

	items := []trendBucket{}
	for rows.Next() {
		var b trendBucket
		if err := rows.Scan(&b.Day, &b.Successes, &b.Failures); err != nil {
			slog.Error("httpapi: learning/trend row scan failed", "error", err)
			continue
		}
		items = append(items, b)
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]any{"items": items})
}
