package cellbuf

import (
	"testing"
)

func TestTabStops(t *testing.T) {
	tests := []struct {
		name     string
		width    int
		interval int
		checks   []struct {
			col      int
			expected bool
		}
	}{
		{
			name:     "default interval of 8",
			width:    24,
			interval: DefaultTabInterval,
			checks: []struct {
				col      int
				expected bool
			}{
				{0, true},   // First tab stop
				{7, false},  // Not a tab stop
				{8, true},   // Second tab stop
				{15, false}, // Not a tab stop
				{16, true},  // Third tab stop
				{23, false}, // Not a tab stop
			},
		},
		{
			name:     "custom interval of 4",
			width:    16,
			interval: 4,
			checks: []struct {
				col      int
				expected bool
			}{
				{0, true},   // First tab stop
				{3, false},  // Not a tab stop
				{4, true},   // Second tab stop
				{7, false},  // Not a tab stop
				{8, true},   // Third tab stop
				{12, true},  // Fourth tab stop
				{15, false}, // Not a tab stop
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			ts := NewTabStops(tt.width, tt.interval)

			// Test initial tab stops
			for _, check := range tt.checks {
				if got := ts.IsStop(check.col); got != check.expected {
					t.Errorf("IsStop(%d) = %v, want %v", check.col, got, check.expected)
				}
			}

			// Test setting a custom tab stop
			customCol := tt.interval + 1
			ts.Set(customCol)
			if !ts.IsStop(customCol) {
				t.Errorf("After Set(%d), IsStop(%d) = false, want true", customCol, customCol)
			}

			// Test resetting a tab stop
			regularStop := tt.interval
			ts.Reset(regularStop)
			if ts.IsStop(regularStop) {
				t.Errorf("After Reset(%d), IsStop(%d) = true, want false", regularStop, regularStop)
			}
		})
	}
}

func TestTabStopsNavigation(t *testing.T) {
	ts := NewTabStops(24, DefaultTabInterval)

	tests := []struct {
		name     string
		col      int
		wantNext int
		wantPrev int
	}{
		{
			name:     "from column 0",
			col:      0,
			wantNext: 8,
			wantPrev: 0,
		},
		{
			name:     "from column 4",
			col:      4,
			wantNext: 8,
			wantPrev: 0,
		},
		{
			name:     "from column 8",
			col:      8,
			wantNext: 16,
			wantPrev: 0,
		},
		{
			name:     "from column 20",
			col:      20,
			wantNext: 23,
			wantPrev: 16,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := ts.Next(tt.col); got != tt.wantNext {
				t.Errorf("Next(%d) = %v, want %v", tt.col, got, tt.wantNext)
			}
			if got := ts.Prev(tt.col); got != tt.wantPrev {
				t.Errorf("Prev(%d) = %v, want %v", tt.col, got, tt.wantPrev)
			}
		})
	}
}

func TestTabStopsClear(t *testing.T) {
	ts := NewTabStops(24, DefaultTabInterval)

	// Verify initial state
	if !ts.IsStop(0) || !ts.IsStop(8) || !ts.IsStop(16) {
		t.Error("Initial tab stops not set correctly")
	}

	// Clear all tab stops
	ts.Clear()

	// Verify all stops are cleared
	for i := 0; i < 24; i++ {
		if ts.IsStop(i) {
			t.Errorf("Tab stop at column %d still set after Clear()", i)
		}
	}
}

func TestTabStopsResize(t *testing.T) {
	tests := []struct {
		name        string
		initialSize int
		newSize     int
		checks      []struct {
			col      int
			expected bool
		}
	}{
		{
			name:        "grow buffer",
			initialSize: 16,
			newSize:     24,
			checks: []struct {
				col      int
				expected bool
			}{
				{0, true},   // Original tab stop
				{8, true},   // Original tab stop
				{16, true},  // New tab stop
				{23, false}, // Not a tab stop
			},
		},
		{
			name:        "same size - no change",
			initialSize: 16,
			newSize:     16,
			checks: []struct {
				col      int
				expected bool
			}{
				{0, true},   // Original tab stop
				{8, true},   // Original tab stop
				{15, false}, // Not a tab stop
			},
		},
		{
			name:        "resize with custom interval",
			initialSize: 8,
			newSize:     16,
			checks: []struct {
				col      int
				expected bool
			}{
				{0, true},   // First tab stop
				{4, true},   // Second tab stop
				{8, true},   // Third tab stop
				{12, true},  // Fourth tab stop
				{15, false}, // Not a tab stop
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			var ts *TabStops
			if tt.name == "resize with custom interval" {
				ts = NewTabStops(tt.initialSize, 4) // Custom interval of 4
			} else {
				ts = DefaultTabStops(tt.initialSize)
			}

			// Verify initial state
			if ts.width != tt.initialSize {
				t.Errorf("Initial width = %d, want %d", ts.width, tt.initialSize)
			}

			// Perform resize
			ts.Resize(tt.newSize)

			// Verify new size
			if ts.width != tt.newSize {
				t.Errorf("After resize, width = %d, want %d", ts.width, tt.newSize)
			}

			// Check tab stops after resize
			for _, check := range tt.checks {
				if got := ts.IsStop(check.col); got != check.expected {
					t.Errorf("After resize, IsStop(%d) = %v, want %v",
						check.col, got, check.expected)
				}
			}

			// Verify stops slice has correct length
			expectedStopsLen := (tt.newSize + (ts.interval - 1)) / ts.interval
			if len(ts.stops) != expectedStopsLen {
				t.Errorf("stops slice length = %d, want %d",
					len(ts.stops), expectedStopsLen)
			}
		})
	}
}

func TestTabStopsResizeEdgeCases(t *testing.T) {
	t.Run("resize to zero", func(t *testing.T) {
		ts := DefaultTabStops(8)
		ts.Resize(0)

		if ts.width != 0 {
			t.Errorf("width = %d, want 0", ts.width)
		}

		// Verify no tab stops are accessible
		if ts.IsStop(0) {
			t.Error("IsStop(0) should return false for zero width")
		}
	})

	t.Run("resize to very large width", func(t *testing.T) {
		ts := DefaultTabStops(8)
		largeWidth := 1000
		ts.Resize(largeWidth)

		// Check some tab stops at higher positions
		checks := []struct {
			col      int
			expected bool
		}{
			{992, true},  // Multiple of 8
			{999, false}, // Not a tab stop
		}

		for _, check := range checks {
			if got := ts.IsStop(check.col); got != check.expected {
				t.Errorf("IsStop(%d) = %v, want %v",
					check.col, got, check.expected)
			}
		}
	})

	t.Run("multiple resizes", func(t *testing.T) {
		ts := DefaultTabStops(8)

		// Perform multiple resizes
		sizes := []int{16, 8, 24, 4}
		for _, size := range sizes {
			ts.Resize(size)

			// Verify basic properties after each resize
			if ts.width != size {
				t.Errorf("width = %d, want %d", ts.width, size)
			}

			// Check first tab stop is always set
			if !ts.IsStop(0) {
				t.Errorf("After resize to %d, IsStop(0) = false, want true", size)
			}
		}
	})
}
