package assignmentgen

import (
	"fmt"
	"testing"

	"boostai-backend/internal/sqlc"

	"github.com/jackc/pgx/v5/pgtype"
)

func TestBuildWeaknessSummaryAggregatesSignals(t *testing.T) {
	rows := []sqlc.ListStudentPlanningPerformanceRow{
		{
			Topic:                    sqlc.NullQuestionTopic{QuestionTopic: sqlc.QuestionTopicFractions, Valid: true},
			QuestionTags:             []string{"fractions", "simplify"},
			IsCorrect:                pgtype.Bool{Bool: false, Valid: true},
			ReviewUnderstandingScore: mustNumeric(t, 0.2),
			ReviewNeedsAttention:     true,
			ReviewIssueReason:        pgtype.Text{String: "Missed simplification", Valid: true},
		},
		{
			Topic:                    sqlc.NullQuestionTopic{QuestionTopic: sqlc.QuestionTopicGeometry, Valid: true},
			QuestionTags:             []string{"geometry", "angles"},
			IsCorrect:                pgtype.Bool{Bool: true, Valid: true},
			ReviewUnderstandingScore: mustNumeric(t, 0.9),
			ReviewIssueReason:        pgtype.Text{String: "Explained angle sum well", Valid: true},
		},
	}

	summary := buildWeaknessSummary(rows)

	if got := summary.TopicScores[sqlc.QuestionTopicFractions]; got != 10 {
		t.Fatalf("expected fractions score 10, got %v", got)
	}
	if got := summary.TopicScores[sqlc.QuestionTopicGeometry]; got != 95 {
		t.Fatalf("expected geometry score 95, got %v", got)
	}
	if len(summary.WeakTags) == 0 || summary.WeakTags[0] != "fractions" {
		t.Fatalf("expected fractions weak tag to rank first, got %#v", summary.WeakTags)
	}
	if len(summary.RecentIssues) != 2 {
		t.Fatalf("expected 2 recent issues, got %d", len(summary.RecentIssues))
	}
}

func TestSelectPersonalizedTopicPrefersWeakestNonPrimary(t *testing.T) {
	summary := WeaknessSummary{
		TopicScores: map[sqlc.QuestionTopic]float64{
			sqlc.QuestionTopicFractions: 35,
			sqlc.QuestionTopicGeometry:  82,
			sqlc.QuestionTopicAlgebra:   61,
		},
	}

	topic, ok := selectPersonalizedTopic(sqlc.QuestionTopicGeometry, summary)
	if !ok {
		t.Fatal("expected personalized topic to be selected")
	}
	if topic != sqlc.QuestionTopicFractions {
		t.Fatalf("expected fractions, got %q", topic)
	}
}

func TestCalculatePersonalizedCountUsesSafeSplit(t *testing.T) {
	if got := calculatePersonalizedCount(10, 0.3, true); got != 3 {
		t.Fatalf("expected 3 personalized questions, got %d", got)
	}
	if got := calculatePersonalizedCount(2, 0.3, true); got != 0 {
		t.Fatalf("expected 0 personalized questions for tiny set, got %d", got)
	}
	if got := calculatePersonalizedCount(5, 0.3, false); got != 0 {
		t.Fatalf("expected 0 personalized questions without weakness topic, got %d", got)
	}
}

func mustNumeric(t *testing.T, value float64) pgtype.Numeric {
	t.Helper()

	var numeric pgtype.Numeric
	if err := numeric.ScanScientific(fmt.Sprintf("%f", value)); err != nil {
		t.Fatalf("failed to build numeric: %v", err)
	}
	return numeric
}
