package app

import "testing"

// scrollOutput must clamp to [0, totalRows-panelHeight] against the same geometry the renderer
// windows to — so PgUp past the top and PgDn past the bottom land exactly on the edges (no
// dead presses unwinding an overshoot).
func TestOutputScrollClampsToBounds(t *testing.T) {
	m := inSessionModel(120, 30)
	msgs := make([]RouterEntry, 0, 60)
	for i := 0; i < 60; i++ {
		msgs = append(msgs, RouterEntry{Role: "router", Content: "a transcript line"})
	}
	m.routerMessages[m.selectedID] = msgs

	w, h := m.outputViewport()
	rows, _ := m.buildTranscriptRows(w)
	max := len(rows) - h
	if max <= 0 {
		t.Fatalf("fixture transcript (%d rows) must exceed panel height (%d) to test scrolling", len(rows), h)
	}

	m.scrollOutput(10_000) // way past the top
	if m.outputScroll != max {
		t.Fatalf("scroll up clamped to %d, want max %d", m.outputScroll, max)
	}
	m.scrollOutput(-10_000) // way past the bottom
	if m.outputScroll != 0 {
		t.Fatalf("scroll down clamped to %d, want 0 (tail-follow)", m.outputScroll)
	}
}

// A transcript that fits the panel never scrolls (stays tail-following).
func TestOutputScrollNoOpWhenFits(t *testing.T) {
	m := inSessionModel(120, 30)
	m.routerMessages[m.selectedID] = []RouterEntry{{Role: "router", Content: "one line"}}
	m.scrollOutput(5)
	if m.outputScroll != 0 {
		t.Fatalf("short transcript should not scroll, got %d", m.outputScroll)
	}
}
