package tui

import (
	"bytes"
	"strings"
	"testing"

	"github.com/charmbracelet/bubbles/list"
	tea "github.com/charmbracelet/bubbletea"
	"github.com/shazow/wifitui/wifi"
)

func TestListModel_NewKey(t *testing.T) {
	m := NewListModel()
	m.Update(tea.WindowSizeMsg{Width: 100, Height: 30})
	nKeyMsg := tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("n")}
	newComp, _ := m.Update(nKeyMsg)

	editModel, ok := newComp.(*EditModel)
	if !ok {
		t.Errorf("expected a new EditModel but got %T", newComp)
		return
	}

	if got, want := editModel.availableContentWidth(), 96; got != want {
		t.Fatalf("expected edit model content width %d, got %d", want, got)
	}

	if got, want := editModel.ssidAdapter.Model.Width, 92; got != want {
		t.Fatalf("expected SSID input width %d, got %d", want, got)
	}
}

func TestListModel_ForgetFlow(t *testing.T) {
	m := NewListModel()
	item1 := connectionItem{Connection: wifi.Connection{SSID: "TestNetwork1", IsKnown: true}}
	item2 := connectionItem{Connection: wifi.Connection{SSID: "TestNetwork2", IsKnown: true}}
	m.list.SetItems([]list.Item{item1, item2})

	// Press 'f' to start forgetting
	fKeyMsg := tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("f")}
	m.Update(fKeyMsg)

	if !m.isForgetting {
		t.Fatal("isForgetting was not set to true")
	}

	// Press 'n' to cancel
	nKeyMsg := tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("n")}
	m.Update(nKeyMsg)

	if m.isForgetting {
		t.Fatal("isForgetting was not cleared after pressing 'n'")
	}

	// Press 'f' again
	m.Update(fKeyMsg)

	// Press 'j' to navigate, should be ignored
	downKeyMsg := tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("j")}
	m.Update(downKeyMsg)

	if !m.isForgetting {
		t.Fatal("isForgetting should not be cleared after pressing a navigation key")
	}

	// Press 'y' to confirm
	yKeyMsg := tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("y")}
	_, cmd := m.Update(yKeyMsg)

	if m.isForgetting {
		t.Fatal("isForgetting was not cleared after pressing 'y'")
	}

	msg := cmd()
	if forgetMsg, ok := msg.(forgetNetworkMsg); !ok {
		t.Errorf("expected a forgetNetworkMsg but got %T", msg)
	} else {
		if forgetMsg.item.SSID != "TestNetwork1" {
			t.Errorf("expected forgetNetworkMsg for 'TestNetwork1' but got for '%s'", forgetMsg.item.SSID)
		}
	}
}

func TestItemDelegate_RenderAPCountAnnotation(t *testing.T) {
	originalTheme := CurrentTheme
	CurrentTheme = NewDefaultTheme()
	CurrentTheme.AccessPointIcon = "📶"
	t.Cleanup(func() {
		CurrentTheme = originalTheme
	})

	d := itemDelegate{listModel: &ListModel{ssidColumnWidth: 30}}
	m := list.New([]list.Item{}, d, 80, 5)

	item := connectionItem{Connection: wifi.Connection{
		SSID:      "Cafe Wifi",
		IsVisible: true,
		AccessPoints: []wifi.AccessPoint{
			{BSSID: "00:00:00:00:00:01"},
			{BSSID: "00:00:00:00:00:02"},
			{BSSID: "00:00:00:00:00:03"},
		},
	}}

	var buf bytes.Buffer
	d.Render(&buf, m, 0, item)
	out := buf.String()

	if !strings.Contains(out, "📶×3") {
		t.Fatalf("expected rendered output to contain AP count annotation, got: %q", out)
	}
}

func TestItemDelegate_RenderNoAnnotationForSingleAP(t *testing.T) {
	originalTheme := CurrentTheme
	CurrentTheme = NewDefaultTheme()
	t.Cleanup(func() {
		CurrentTheme = originalTheme
	})

	d := itemDelegate{listModel: &ListModel{ssidColumnWidth: 30}}
	m := list.New([]list.Item{}, d, 80, 5)

	item := connectionItem{Connection: wifi.Connection{
		SSID:         "Home Wifi",
		IsVisible:    true,
		AccessPoints: []wifi.AccessPoint{{BSSID: "00:00:00:00:00:01"}},
	}}

	var buf bytes.Buffer
	d.Render(&buf, m, 0, item)
	out := buf.String()

	if strings.Contains(out, "×1") {
		t.Fatalf("expected no AP count annotation for a single AP, got: %q", out)
	}
}
