package catalog

import (
	"bytes"
	"context"
	"strings"
	"testing"

	"github.com/a-h/templ"
)

func TestPagesIncludeTokensAndButtons(t *testing.T) {
	pages := Pages()

	if len(pages) == 0 {
		t.Fatal("expected catalog pages")
	}

	var hasTokens bool
	var hasButtons bool
	for _, page := range pages {
		switch page.Slug {
		case "tokens":
			hasTokens = true
		case "buttons":
			hasButtons = true
		}
	}

	if !hasTokens {
		t.Fatal("expected tokens page")
	}
	if !hasButtons {
		t.Fatal("expected buttons page")
	}
}

func TestPagesIncludePrimitiveCatalogCoverage(t *testing.T) {
	for _, slug := range []string{
		"badges",
		"icon-buttons",
		"inputs",
		"selects",
		"form-fields",
		"modals",
		"spacing",
		"tables",
		"empty-states",
		"cards",
	} {
		if _, ok := FindPage(slug); !ok {
			t.Fatalf("expected catalog page %q", slug)
		}
	}
}

func TestButtonPageExamplesRenderRealPrimitives(t *testing.T) {
	page, ok := FindPage("buttons")
	if !ok {
		t.Fatal("expected buttons page")
	}
	if len(page.Examples) == 0 {
		t.Fatal("expected button examples")
	}

	html := renderToString(t, page.Examples[0].Preview)
	for _, want := range []string{
		`ui-button`,
		`ui-button-solid`,
		`ui-button-default`,
		`Nouveau projet`,
	} {
		if !strings.Contains(html, want) {
			t.Fatalf("expected %q in %q", want, html)
		}
	}
}

func TestCatalogPageRendersMetadataAndExamples(t *testing.T) {
	page, ok := FindPage("tokens")
	if !ok {
		t.Fatal("expected tokens page")
	}

	html := renderToString(t, CatalogPage(page))
	for _, want := range []string{
		`Design System`,
		page.Title,
		`catalog-example`,
	} {
		if !strings.Contains(html, want) {
			t.Fatalf("expected %q in %q", want, html)
		}
	}
}

func TestCatalogIndexLinksToPrimitivePages(t *testing.T) {
	html := renderToString(t, CatalogIndex(Pages()))

	for _, want := range []string{
		`href="./inputs.html"`,
		`href="./buttons.html"`,
		`class="catalog-page-link-card"`,
	} {
		if !strings.Contains(html, want) {
			t.Fatalf("expected %q in %q", want, html)
		}
	}
}

func TestCatalogPageRendersSharedNavigationWithActivePage(t *testing.T) {
	page, ok := FindPage("inputs")
	if !ok {
		t.Fatal("expected inputs page")
	}

	html := renderToString(t, CatalogPage(page))
	for _, want := range []string{
		`href="./index.html"`,
		`href="./buttons.html"`,
		`href="./inputs.html"`,
		`catalog-nav-link is-active`,
	} {
		if !strings.Contains(html, want) {
			t.Fatalf("expected %q in %q", want, html)
		}
	}
}

func TestPrimitiveExamplesRenderRealMarkup(t *testing.T) {
	testCases := []struct {
		slug string
		want []string
	}{
		{slug: "badges", want: []string{`ui-badge`, `En cours`}},
		{slug: "icon-buttons", want: []string{`borderless-icon-button`, `aria-label="Supprimer le projet"`}},
		{slug: "inputs", want: []string{`class="ui-input"`, `placeholder="Nom du projet"`}},
		{slug: "selects", want: []string{`class="ui-select"`, `class="ui-select-control"`}},
		{slug: "form-fields", want: []string{`ui-form-field`, `ui-form-label`}},
		{slug: "modals", want: []string{`ui-modal-panel`, `Créer le projet`}},
		{slug: "tables", want: []string{`class="ui-table"`, `Table View`}},
		{slug: "empty-states", want: []string{`ui-empty-state`, `Aucun projet trouvé`}},
		{slug: "cards", want: []string{`ui-card`, `Header`}},
	}

	for _, tt := range testCases {
		page, ok := FindPage(tt.slug)
		if !ok {
			t.Fatalf("expected page %q", tt.slug)
		}
		if len(page.Examples) == 0 {
			t.Fatalf("expected examples for %q", tt.slug)
		}

		html := renderToString(t, page.Examples[0].Preview)
		for _, want := range tt.want {
			if !strings.Contains(html, want) {
				t.Fatalf("page %q expected %q in %q", tt.slug, want, html)
			}
		}
	}
}

func TestSpacingPageRendersSpacingPrimitives(t *testing.T) {
	page, ok := FindPage("spacing")
	if !ok {
		t.Fatal("expected spacing page")
	}

	html := renderToString(t, CatalogPage(page))
	for _, want := range []string{
		`ui-space-x`,
		`ui-space-y`,
	} {
		if !strings.Contains(html, want) {
			t.Fatalf("spacing page expected %q in %q", want, html)
		}
	}
}

func renderToString(t *testing.T, component templ.Component) string {
	t.Helper()

	var buf bytes.Buffer
	if err := component.Render(context.Background(), &buf); err != nil {
		t.Fatalf("render component: %v", err)
	}
	return buf.String()
}
