package compaction

import (
	"testing"

	"chat-switchboard/treepath"
)

func TestEstimateTokens(t *testing.T) {
	tests := []struct {
		input string
		want  int
	}{
		{"", 0},
		{"a", 1},
		{"abcd", 1},
		{"abcde", 2},
		{"Hello, world!", 4}, // 13 chars → ceil(13/4) = 4
		{string(make([]byte, 100)), 25},
		{string(make([]byte, 1000)), 250},
	}
	for _, tt := range tests {
		got := EstimateTokens(tt.input)
		if got != tt.want {
			t.Errorf("EstimateTokens(%d chars) = %d, want %d", len(tt.input), got, tt.want)
		}
	}
}

func TestEstimatePath(t *testing.T) {
	path := []treepath.PathMessage{
		{Content: string(make([]byte, 40))},  // 10 tokens + 4 overhead = 14
		{Content: string(make([]byte, 80))},  // 20 tokens + 4 overhead = 24
		{Content: string(make([]byte, 120))}, // 30 tokens + 4 overhead = 34
	}
	got := EstimatePath(path)
	// (10+4) + (20+4) + (30+4) = 72
	if got != 72 {
		t.Errorf("EstimatePath = %d, want 72", got)
	}
}

func TestEstimatePathFromSummary_NoSummary(t *testing.T) {
	path := make([]treepath.PathMessage, 10)
	for i := range path {
		path[i] = treepath.PathMessage{Role: "user", Content: string(make([]byte, 40))}
	}

	tokens, count, ok := EstimatePathFromSummary(path, 8)
	if !ok {
		t.Fatal("expected ok=true for 10 messages >= minMessages=8")
	}
	if count != 10 {
		t.Errorf("count = %d, want 10", count)
	}
	// Each: 10 tokens + 4 overhead = 14, × 10 = 140
	if tokens != 140 {
		t.Errorf("tokens = %d, want 140", tokens)
	}
}

func TestEstimatePathFromSummary_TooFew(t *testing.T) {
	path := make([]treepath.PathMessage, 3)
	for i := range path {
		path[i] = treepath.PathMessage{Role: "user", Content: "hello"}
	}

	_, _, ok := EstimatePathFromSummary(path, 8)
	if ok {
		t.Error("expected ok=false for 3 messages < minMessages=8")
	}
}

func TestEstimatePathFromSummary_SkipsSystemMessages(t *testing.T) {
	path := []treepath.PathMessage{
		{Role: "system", Content: "You are helpful."},
		{Role: "user", Content: string(make([]byte, 40))},
		{Role: "assistant", Content: string(make([]byte, 40))},
	}

	tokens, count, ok := EstimatePathFromSummary(path, 1)
	if !ok {
		t.Fatal("expected ok=true")
	}
	// system skipped, 2 non-system messages
	if count != 2 {
		t.Errorf("count = %d, want 2", count)
	}
	if tokens != 28 { // 2 × (10 + 4) = 28
		t.Errorf("tokens = %d, want 28", tokens)
	}
}
