package tui

import (
	"strings"
	"testing"

	tea "github.com/charmbracelet/bubbletea"
)

func TestConfirmModel_DefaultsToYes(t *testing.T) {
	m := confirmModel{prompt: "Download test?", yes: true}
	if !m.yes {
		t.Error("should default to yes")
	}
}

func TestConfirmModel_View_ContainsPrompt(t *testing.T) {
	m := confirmModel{prompt: "Download qwen3:8b?", yes: true}
	got := m.View()
	if !strings.Contains(got, "Download qwen3:8b?") {
		t.Error("should contain the prompt text")
	}
}

func TestConfirmModel_View_ContainsButtons(t *testing.T) {
	m := confirmModel{prompt: "Download?", yes: true}
	got := m.View()
	if !strings.Contains(got, "Yes") {
		t.Error("should contain Yes button")
	}
	if !strings.Contains(got, "No") {
		t.Error("should contain No button")
	}
}

func TestConfirmModel_View_ContainsCustomButtons(t *testing.T) {
	m := confirmModel{
		prompt:   "Connect a messaging app now?",
		yesLabel: "Yes",
		noLabel:  "Set up later",
		yes:      true,
	}
	got := m.View()
	if !strings.Contains(got, "Yes") {
		t.Error("should contain custom yes button")
	}
	if !strings.Contains(got, "Set up later") {
		t.Error("should contain custom no button")
	}
}

func TestConfirmModel_View_ContainsHelp(t *testing.T) {
	m := confirmModel{prompt: "Download?", yes: true}
	got := m.View()
	if !strings.Contains(got, "enter confirm") {
		t.Error("should contain help text")
	}
}

func TestConfirmModel_View_ClearsAfterConfirm(t *testing.T) {
	m := confirmModel{prompt: "Download?", confirmed: true}
	if m.View() != "" {
		t.Error("View should return empty string after confirmation")
	}
}

func TestConfirmModel_View_ClearsAfterCancel(t *testing.T) {
	m := confirmModel{prompt: "Download?", cancelled: true}
	if m.View() != "" {
		t.Error("View should return empty string after cancellation")
	}
}

func TestConfirmModel_EnterConfirmsYes(t *testing.T) {
	m := confirmModel{prompt: "Download?", yes: true}
	updated, cmd := m.Update(tea.KeyMsg{Type: tea.KeyEnter})
	fm := updated.(confirmModel)
	if !fm.confirmed {
		t.Error("enter should set confirmed=true")
	}
	if !fm.yes {
		t.Error("enter with yes selected should keep yes=true")
	}
	if cmd == nil {
		t.Error("enter should return tea.Quit")
	}
}

func TestConfirmModel_EnterConfirmsNo(t *testing.T) {
	m := confirmModel{prompt: "Download?", yes: false}
	updated, cmd := m.Update(tea.KeyMsg{Type: tea.KeyEnter})
	fm := updated.(confirmModel)
	if !fm.confirmed {
		t.Error("enter should set confirmed=true")
	}
	if fm.yes {
		t.Error("enter with no selected should keep yes=false")
	}
	if cmd == nil {
		t.Error("enter should return tea.Quit")
	}
}

func TestConfirmModel_EscCancels(t *testing.T) {
	m := confirmModel{prompt: "Download?", yes: true}
	updated, cmd := m.Update(tea.KeyMsg{Type: tea.KeyEsc})
	fm := updated.(confirmModel)
	if !fm.cancelled {
		t.Error("esc should set cancelled=true")
	}
	if cmd == nil {
		t.Error("esc should return tea.Quit")
	}
}

func TestConfirmModel_CtrlCCancels(t *testing.T) {
	m := confirmModel{prompt: "Download?", yes: true}
	updated, cmd := m.Update(tea.KeyMsg{Type: tea.KeyCtrlC})
	fm := updated.(confirmModel)
	if !fm.cancelled {
		t.Error("ctrl+c should set cancelled=true")
	}
	if cmd == nil {
		t.Error("ctrl+c should return tea.Quit")
	}
}

func TestConfirmModel_NDoesNothing(t *testing.T) {
	m := confirmModel{prompt: "Download?", yes: true}
	updated, cmd := m.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'n'}})
	fm := updated.(confirmModel)
	if fm.cancelled {
		t.Error("'n' should not cancel")
	}
	if fm.confirmed {
		t.Error("'n' should not confirm")
	}
	if cmd != nil {
		t.Error("'n' should not quit")
	}
}

func TestConfirmModel_YDoesNothing(t *testing.T) {
	m := confirmModel{prompt: "Download?", yes: false}
	updated, cmd := m.Update(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'y'}})
	fm := updated.(confirmModel)
	if fm.confirmed {
		t.Error("'y' should not confirm")
	}
	if fm.yes {
		t.Error("'y' should not change selection")
	}
	if cmd != nil {
		t.Error("'y' should not quit")
	}
}

func TestConfirmModel_ArrowKeysNavigate(t *testing.T) {
	m := confirmModel{prompt: "Download?", yes: true}

	// Right moves to No
	updated, _ := m.Update(tea.KeyMsg{Type: tea.KeyRight})
	fm := updated.(confirmModel)
	if fm.yes {
		t.Error("right should move to No")
	}
	if fm.confirmed || fm.cancelled {
		t.Error("navigation should not confirm or cancel")
	}

	// Left moves back to Yes
	updated, _ = fm.Update(tea.KeyMsg{Type: tea.KeyLeft})
	fm = updated.(confirmModel)
	if !fm.yes {
		t.Error("left should move to Yes")
	}
}

func TestConfirmModel_TabDoesNothing(t *testing.T) {
	m := confirmModel{prompt: "Download?", yes: true}

	updated, _ := m.Update(tea.KeyMsg{Type: tea.KeyTab})
	fm := updated.(confirmModel)
	if !fm.yes {
		t.Error("tab should not change selection")
	}
	if fm.confirmed || fm.cancelled {
		t.Error("tab should not confirm or cancel")
	}
}

func TestConfirmModel_WindowSizeUpdatesWidth(t *testing.T) {
	m := confirmModel{prompt: "Download?"}
	updated, _ := m.Update(tea.WindowSizeMsg{Width: 100, Height: 40})
	fm := updated.(confirmModel)
	if fm.width != 100 {
		t.Errorf("expected width 100, got %d", fm.width)
	}
}

func TestConfirmModel_ResizeEntersAltScreen(t *testing.T) {
	m := confirmModel{prompt: "Download?", width: 80}
	_, cmd := m.Update(tea.WindowSizeMsg{Width: 100, Height: 40})
	if cmd == nil {
		t.Error("resize (width already set) should return a command")
	}
}

func TestConfirmModel_InitialWindowSizeNoAltScreen(t *testing.T) {
	m := confirmModel{prompt: "Download?"}
	_, cmd := m.Update(tea.WindowSizeMsg{Width: 80, Height: 40})
	if cmd != nil {
		t.Error("initial WindowSizeMsg should not return a command")
	}
}

func TestConfirmModel_ViewMaxWidth(t *testing.T) {
	m := confirmModel{prompt: "Download?", yes: true, width: 40}
	got := m.View()
	// Just ensure it doesn't panic and returns content
	if got == "" {
		t.Error("View with width set should still return content")
	}
}
