// Theme token ownership and ANSI background continuity are cross-screen
// visual invariants. Both fail silently in a real terminal — a screen that
// drifts from the palette, a selection tint cut short by a reset — and no
// daemon e2e observes terminal rendering.
package tui

import (
	"os"
	"regexp"
	"strings"
	"testing"
)

// Colors are chosen in the theme alone. A screen that picks its own drifts
// from the rest, which is how the session screen grew a second palette.
func TestColorsComeFromTheTheme(t *testing.T) {
	owners := map[string]bool{"theme.go": true, "ink.go": true, "ink_unix.go": true, "ink_other.go": true}
	raw := regexp.MustCompile(`lipgloss\.Color\(|AdaptiveColor|\\x1b\[(3\d|4\d|9\d|7|38;|48;)|Faint\(true\)|Reverse\(true\)|"#[0-9a-fA-F]{6}"|\.Foreground\(|\)\.Background\(`)
	entries, err := os.ReadDir(".")
	if err != nil {
		t.Fatal(err)
	}
	for _, e := range entries {
		name := e.Name()
		if !strings.HasSuffix(name, ".go") || strings.HasSuffix(name, "_test.go") || owners[name] {
			continue
		}
		src, err := os.ReadFile(name)
		if err != nil {
			t.Fatal(err)
		}
		for i, line := range strings.Split(string(src), "\n") {
			if raw.MatchString(line) {
				t.Errorf("%s:%d picks its own color, use a theme token: %s", name, i+1, strings.TrimSpace(line))
			}
		}
	}
}

// A full reset comes as "ESC[m" from Lip Gloss and "ESC[0m" from the raw ink;
// the selection surface and a diff row's tint must survive both.
func TestBackgroundsOutliveStyledSpans(t *testing.T) {
	span := DefaultStyles.Muted.Render("a")
	marked := DefaultStyles.Selected.Render("\x00")
	open := marked[:strings.IndexByte(marked, 0)]
	if line := selectedLine(span+" b", 0); !strings.Contains(line, open+" b") {
		t.Errorf("selection surface ends at the first span: %q", line)
	}
	if kept := keepBackground(span); strings.Contains(kept, "\x1b[m") || strings.Contains(kept, "\x1b[0m") {
		t.Errorf("a span still resets the row tint: %q", kept)
	}
}
