package model

import (
	"testing"

	tea "charm.land/bubbletea/v2"

	"github.com/bjarneo/cliamp/playlist"
)

func TestHandlePasteRoutesToActiveInput(t *testing.T) {
	tests := []struct {
		name    string
		model   Model
		content string
		check   func(t *testing.T, m *Model)
	}{
		{
			name:    "keymap search",
			model:   Model{keymap: keymapOverlay{visible: true}},
			content: "ctrl",
			check: func(t *testing.T, m *Model) {
				if m.keymap.search != "ctrl" {
					t.Fatalf("keymap.search = %q, want %q", m.keymap.search, "ctrl")
				}
			},
		},
		{
			name:    "net search",
			model:   Model{netSearch: netSearchState{active: true, query: "hello "}},
			content: "world",
			check: func(t *testing.T, m *Model) {
				if m.netSearch.query != "hello world" {
					t.Fatalf("netSearch.query = %q, want %q", m.netSearch.query, "hello world")
				}
			},
		},
		{
			name:    "search appends and filters",
			model:   Model{search: searchState{active: true, query: "ja"}, playlist: playlist.New()},
			content: "zz",
			check: func(t *testing.T, m *Model) {
				if m.search.query != "jazz" {
					t.Fatalf("search.query = %q, want %q", m.search.query, "jazz")
				}
			},
		},
		{
			name:    "jump input",
			model:   Model{jumping: true, jumpInput: "1:"},
			content: "30",
			check: func(t *testing.T, m *Model) {
				if m.jumpInput != "1:30" {
					t.Fatalf("jumpInput = %q, want %q", m.jumpInput, "1:30")
				}
			},
		},
		{
			name:    "url input",
			model:   Model{urlInputting: true},
			content: "https://example.com/song.mp3",
			check: func(t *testing.T, m *Model) {
				if m.urlInput != "https://example.com/song.mp3" {
					t.Fatalf("urlInput = %q, want %q", m.urlInput, "https://example.com/song.mp3")
				}
			},
		},
		{
			name: "playlist manager new name",
			model: Model{plManager: plManagerState{
				visible: true,
				screen:  plMgrScreenNewName,
			}},
			content: "My Playlist",
			check: func(t *testing.T, m *Model) {
				if m.plManager.newName != "My Playlist" {
					t.Fatalf("plManager.newName = %q, want %q", m.plManager.newName, "My Playlist")
				}
			},
		},
		{
			name: "spotify search input",
			model: Model{spotSearch: spotSearchState{
				visible: true,
				screen:  spotSearchInput,
			}},
			content: "arctic monkeys",
			check: func(t *testing.T, m *Model) {
				if m.spotSearch.query != "arctic monkeys" {
					t.Fatalf("spotSearch.query = %q, want %q", m.spotSearch.query, "arctic monkeys")
				}
			},
		},
		{
			name: "spotify new name",
			model: Model{spotSearch: spotSearchState{
				visible: true,
				screen:  spotSearchNewName,
			}},
			content: "New Playlist",
			check: func(t *testing.T, m *Model) {
				if m.spotSearch.newName != "New Playlist" {
					t.Fatalf("spotSearch.newName = %q, want %q", m.spotSearch.newName, "New Playlist")
				}
			},
		},
		{
			name:    "provider search (non-catalog)",
			model:   Model{provSearch: provSearchState{active: true, query: "rock"}},
			content: " ballads",
			check: func(t *testing.T, m *Model) {
				if m.provSearch.query != "rock ballads" {
					t.Fatalf("provSearch.query = %q, want %q", m.provSearch.query, "rock ballads")
				}
			},
		},
		{
			name: "nav browser search",
			model: Model{navBrowser: navBrowserState{
				visible:   true,
				mode:      navBrowseModeByAlbum,
				searching: true,
			}},
			content: "album",
			check: func(t *testing.T, m *Model) {
				if m.navBrowser.search != "album" {
					t.Fatalf("navBrowser.search = %q, want %q", m.navBrowser.search, "album")
				}
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			m := tt.model
			if cmd := m.handlePaste(tt.content); cmd != nil {
				t.Fatalf("handlePaste returned non-nil cmd")
			}
			tt.check(t, &m)
		})
	}
}

func TestHandlePasteEmptyContentIsNoop(t *testing.T) {
	m := Model{netSearch: netSearchState{active: true, query: "before"}}

	if cmd := m.handlePaste(""); cmd != nil {
		t.Fatalf("handlePaste(\"\") returned non-nil cmd")
	}
	if m.netSearch.query != "before" {
		t.Fatalf("query changed on empty paste: got %q", m.netSearch.query)
	}
}

func TestHandlePasteNoInputActiveIsNoop(t *testing.T) {
	m := Model{focus: focusPlaylist}

	if cmd := m.handlePaste("ignored text"); cmd != nil {
		t.Fatalf("handlePaste returned non-nil cmd when no input active")
	}
}

func TestHandlePastePriorityOrder(t *testing.T) {
	// When multiple input states are active, the highest-priority one wins.
	// Nav browser search has higher priority than net search.
	m := Model{
		navBrowser: navBrowserState{
			visible:   true,
			mode:      navBrowseModeByAlbum,
			searching: true,
		},
		netSearch: netSearchState{active: true},
	}

	m.handlePaste("test")

	if m.navBrowser.search != "test" {
		t.Fatalf("navBrowser.search = %q, want %q", m.navBrowser.search, "test")
	}
	if m.netSearch.query != "" {
		t.Fatalf("netSearch.query = %q, want empty (lower priority)", m.netSearch.query)
	}
}

func TestUpdateRoutesPasteMsg(t *testing.T) {
	m := Model{netSearch: netSearchState{active: true}}

	next, cmd := m.Update(tea.PasteMsg{Content: "pasted"})
	got := next.(Model)

	if cmd != nil {
		t.Fatalf("Update(PasteMsg) cmd = %v, want nil", cmd)
	}
	if got.netSearch.query != "pasted" {
		t.Fatalf("netSearch.query = %q, want %q", got.netSearch.query, "pasted")
	}
}
