package web

import (
	"bytes"
	"context"
	"git.d-ma.be/mathias/tapir/internal/adapters/store"
	"strings"
	"testing"
)

func TestParseYouTubeVideoID(t *testing.T) {
	const id = "dQw4w9WgXcQ"
	ok := []struct {
		name, in string
	}{
		{"watch", "https://www.youtube.com/watch?v=" + id},
		{"watch no www", "https://youtube.com/watch?v=" + id},
		{"watch m", "https://m.youtube.com/watch?v=" + id},
		{"watch extra params", "https://www.youtube.com/watch?v=" + id + "&t=42s&list=PLxyz"},
		{"watch param after", "https://www.youtube.com/watch?list=PLxyz&v=" + id},
		{"short link", "https://youtu.be/" + id},
		{"short link param", "https://youtu.be/" + id + "?si=abcd&t=1"},
		{"shorts", "https://www.youtube.com/shorts/" + id},
		{"embed", "https://www.youtube.com/embed/" + id},
		{"bare id", id},
		{"http scheme", "http://youtube.com/watch?v=" + id},
		{"no scheme", "youtube.com/watch?v=" + id},
		{"trailing space", "  https://youtu.be/" + id + "  "},
	}
	for _, c := range ok {
		t.Run(c.name, func(t *testing.T) {
			got, err := parseYouTubeVideoID(c.in)
			if err != nil {
				t.Fatalf("parseYouTubeVideoID(%q) error: %v", c.in, err)
			}
			if got != id {
				t.Fatalf("parseYouTubeVideoID(%q) = %q, want %q", c.in, got, id)
			}
		})
	}

	bad := []struct {
		name, in string
	}{
		{"empty", ""},
		{"blank", "   "},
		{"vimeo", "https://vimeo.com/123456789"},
		{"other host", "https://example.com/watch?v=" + id},
		{"watch no id", "https://www.youtube.com/watch?v="},
		{"short id", "https://youtu.be/abc"},
		{"long id", "https://youtu.be/" + id + "extra"},
		{"bad chars", "https://youtu.be/dQw4w9Wg!cQ"},
		{"not a url", "just some text"},
		{"channel url", "https://www.youtube.com/@somechannel"},
	}
	for _, c := range bad {
		t.Run("reject "+c.name, func(t *testing.T) {
			if got, err := parseYouTubeVideoID(c.in); err == nil {
				t.Fatalf("parseYouTubeVideoID(%q) = %q, want error", c.in, got)
			}
		})
	}
}

func TestListPageShowsPasteFormOnlyWhenConnected(t *testing.T) {
	render := func(connected bool) string {
		var buf bytes.Buffer
		if err := ListPage(listBuckets{}, Filter{}, PipelineStats{}, "", connected, nil, true).Render(context.Background(), &buf); err != nil {
			t.Fatalf("render: %v", err)
		}
		return buf.String()
	}

	html := render(true)
	if !strings.Contains(html, `name="url"`) || !strings.Contains(html, `action="/paste"`) {
		t.Errorf("connected feed must show the paste form")
	}
	if strings.Contains(render(false), `name="url"`) {
		t.Errorf("disconnected feed must not show the paste form")
	}
}

func TestFilterMatchesMultipleChannels(t *testing.T) {
	f := Filter{Channels: []string{"Acme", "Zeta"}}
	row := func(ch string) store.SummaryRow { return store.SummaryRow{ChannelTitle: ch, Summarized: true} }

	rows := []store.SummaryRow{row("Acme"), row("Beta"), row("Zeta")}
	got := f.apply(rows)
	if len(got) != 2 || got[0].ChannelTitle != "Acme" || got[1].ChannelTitle != "Zeta" {
		t.Fatalf("multi-channel filter = %+v, want Acme+Zeta only", got)
	}

	// Empty selection = no channel constraint (all pass).
	if n := len(Filter{}.apply(rows)); n != 3 {
		t.Fatalf("no channel filter should pass all rows, got %d", n)
	}
}
