package pages

import (
	"bytes"
	"io"
	"log/slog"
	"strings"
	"testing"

	"tangled.org/core/appview/config"
	"tangled.org/core/appview/oauth"
	"tangled.org/core/appview/pages/repoinfo"
	"tangled.org/core/idresolver"
)

// the spindle picker is free text with a datalist of recently used spindles, and
// is shared by repo-new, repo-fork and repo-settings/pipelines. Rendering catches
// what parsing can't: a mistyped fragment name or dict key only fails on execute.
func TestSpindleInputRenders(t *testing.T) {
	cfg := &config.Config{}
	p := NewPages(cfg, idresolver.DefaultResolver("https://plc.test"), nil, nil, slog.New(slog.NewTextHandler(io.Discard, nil)))

	cases := []struct {
		name   string
		stack  []string
		define string
		params any
		want   []string
	}{
		{
			name:   "repo/new",
			stack:  []string{"repo/new"},
			define: "spindle",
			params: NewRepoParams{Spindles: []string{"spindle.example.com"}},
			want:   []string{`list="spindle-options"`, `<option value="spindle.example.com">`, `value=""`},
		},
		{
			name:   "repo/fork",
			stack:  []string{"repo/fork"},
			define: "content",
			params: ForkRepoParams{
				BaseParams: BaseParams{
					LoggedInUser: &oauth.MultiAccountUser{Did: "did:plc:test"},
				},
				Spindles: []string{"spindle.example.com"},
				RepoInfo: repoinfo.RepoInfo{OwnerDid: "did:plc:test", Name: "test-repo"},
			},
			want: []string{`list="spindle-options"`, `<option value="spindle.example.com">`},
		},
		{
			name:   "repo/settings/pipelines",
			stack:  []string{"repo/settings/pipelines"},
			define: "spindleSettings",
			params: RepoPipelineSettingsParams{
				Spindles:       []string{"spindle.example.com"},
				CurrentSpindle: "spindle.tangled.sh",
				RepoInfo: repoinfo.RepoInfo{
					OwnerDid: "did:plc:test",
					Name:     "test-repo",
					Roles:    repoinfo.RolesInRepo{Roles: []string{"repo:owner"}},
				},
			},
			// the current spindle is prefilled, and clearing the field removes it
			want: []string{`value="spindle.tangled.sh"`, `<option value="spindle.example.com">`},
		},
	}

	for _, c := range cases {
		t.Run(c.name, func(t *testing.T) {
			tpl, err := p.rawParse(c.stack...)
			if err != nil {
				t.Fatalf("parse %v: %v", c.stack, err)
			}

			var buf bytes.Buffer
			if err := tpl.ExecuteTemplate(&buf, c.define, c.params); err != nil {
				t.Fatalf("execute %q: %v", c.define, err)
			}

			got := buf.String()
			for _, want := range c.want {
				if !strings.Contains(got, want) {
					t.Errorf("output missing %q:\n%s", want, got)
				}
			}
		})
	}
}
