package webui

import (
	"strings"
	"testing"
)

// What a table renders on the SERVER, in each of the three shapes. The distinction
// exists because a saved layout lives in localStorage, which the server cannot read:
//
//   - no persistence            -> nothing can arrive late. Render in full. (default)
//   - persistence               -> a skeleton, until the client says what the layout is.
//   - persistence + ShowWhile.. -> render the DECLARED table at once, and accept that
//     the client may rearrange it (the flash).

func ssrTable(t *testing.T, cols AutoTableColumnOptions) string {
	t.Helper()
	s := NewAutoTableState([]AutoTableColumn{
		{Key: "name", DisplayName: "Client", SortIdentifier: "Name"},
	}, AutoTableStateOptions{Columns: cols})
	s.SetRows([]any{calcRec{"Ada", "100", "40"}})
	return renderNode(s.Render())
}

// A plain, static table — no personalisation — must server-render its CONTENT. This
// is the common case and it must not pay for a feature it does not use.
func TestStaticTableServerRendersInFull(t *testing.T) {
	html := ssrTable(t, AutoTableColumnOptions{})

	if !strings.Contains(html, "Client") {
		t.Errorf("a table with no persistence must SSR its content:\n%s", html)
	}
	if strings.Contains(html, `aria-busy="true"`) {
		t.Error("a table with no persistence rendered a skeleton — it has nothing to wait for")
	}
}

// Turn persistence on and the server no longer knows the layout, so it holds a
// skeleton rather than showing a table that is about to rearrange itself.
func TestPersistedTableHoldsASkeletonUntilTheLayoutSettles(t *testing.T) {
	html := ssrTable(t, AutoTableColumnOptions{StorageKey: "k"})

	if !strings.Contains(html, `aria-busy="true"`) {
		t.Errorf("a persisted table should hold a skeleton on the server:\n%s", html)
	}
	if strings.Contains(html, "Client") {
		t.Error("it rendered table content — a user with a saved layout would watch it rearrange")
	}
}

// ...unless the caller says it would rather have the content and accept the flash.
func TestShowWhileRestoringServerRendersInFull(t *testing.T) {
	html := ssrTable(t, AutoTableColumnOptions{StorageKey: "k", ShowWhileRestoring: true})

	if !strings.Contains(html, "Client") {
		t.Errorf("ShowWhileRestoring must SSR the declared table:\n%s", html)
	}
	if strings.Contains(html, `aria-busy="true"`) {
		t.Error("ShowWhileRestoring rendered a skeleton anyway")
	}
}

// And once the layout has settled, a persisted table renders normally.
func TestPersistedTableRevealsAfterRestore(t *testing.T) {
	s := NewAutoTableState([]AutoTableColumn{
		{Key: "name", DisplayName: "Client", SortIdentifier: "Name"},
	}, AutoTableStateOptions{Columns: AutoTableColumnOptions{StorageKey: "k"}})
	s.SetRows([]any{calcRec{"Ada", "100", "40"}})

	if s.LayoutSettled() {
		t.Fatal("a persisted table should not start settled")
	}
	s.RestoreLayout() // nothing to restore here; it just settles

	if !s.LayoutSettled() {
		t.Fatal("RestoreLayout did not settle the layout")
	}
	if html := renderNode(s.Render()); !strings.Contains(html, "Client") {
		t.Errorf("the table did not reveal after restore:\n%s", html)
	}
}
