package zddc

import (
	"os"
	"path/filepath"
	"strings"
	"testing"
)

func TestValidPartyName(t *testing.T) {
	ok := []string{"0330C1", "Acme", "Acme.Inc", "Acme-Subsidiary", "a", "0", "0330C1.draft", "X-Y-Z"}
	bad := []string{"", ".hidden", "_underscore", "Acme/sub", "Acme Inc", "Acme(Inc)", "Acme,Inc", "..", "-leading-dash"}
	for _, s := range ok {
		if !ValidPartyName(s) {
			t.Errorf("ValidPartyName(%q) = false, want true", s)
		}
	}
	for _, s := range bad {
		if ValidPartyName(s) {
			t.Errorf("ValidPartyName(%q) = true, want false", s)
		}
	}
}

func TestIsPlanReviewURL(t *testing.T) {
	cases := []struct {
		url  string
		want bool
	}{
		{"/Project/archive/Acme/received/Acme-0042", true},
		{"/Project/archive/Acme/received/Acme-0042/", true},
		{"/Project/archive/Acme/received", false},
		{"/Project/archive/Acme/received/", false},
		{"/Project/archive/Acme/received/Acme-0042/file.pdf", false},
		{"/Project/archive/Acme/issued/Acme-0042/", false},
		{"/Project/archive/Acme", false},
		{"/", false},
		{"", false},
	}
	for _, tc := range cases {
		if got := IsPlanReviewURL(tc.url); got != tc.want {
			t.Errorf("IsPlanReviewURL(%q) = %v, want %v", tc.url, got, tc.want)
		}
	}
}

func TestIsSSRCreateURL(t *testing.T) {
	cases := []struct {
		url    string
		want   string
		wantOK bool
	}{
		{"/Project/ssr/form.html", "Project", true},
		{"/Other-Project/ssr/form.html", "Other-Project", true},
		{"/Project/ssr/", "", false},
		{"/Project/ssr/Acme.yaml.html", "", false},
		{"/Project/mdl/form.html", "", false},
		{"/.hidden/ssr/form.html", "", false},
	}
	for _, tc := range cases {
		got, ok := IsSSRCreateURL(tc.url)
		if ok != tc.wantOK || got != tc.want {
			t.Errorf("IsSSRCreateURL(%q) = (%q,%v) want (%q,%v)", tc.url, got, ok, tc.want, tc.wantOK)
		}
	}
}

func TestIsRollupCreateURL(t *testing.T) {
	cases := []struct {
		url      string
		wantProj string
		wantPeer string
		wantOK   bool
	}{
		{"/Project/mdl/form.html", "Project", "mdl", true},
		{"/Project/rsk/form.html", "Project", "rsk", true},
		{"/Project/ssr/form.html", "", "", false},
		{"/Project/mdl/Acme/form.html", "", "", false},
		{"/.hidden/mdl/form.html", "", "", false},
	}
	for _, tc := range cases {
		proj, peer, ok := IsRollupCreateURL(tc.url)
		if ok != tc.wantOK || proj != tc.wantProj || peer != tc.wantPeer {
			t.Errorf("IsRollupCreateURL(%q) = (%q,%q,%v) want (%q,%q,%v)", tc.url, proj, peer, ok, tc.wantProj, tc.wantPeer, tc.wantOK)
		}
	}
}

func TestStripYAMLHTML(t *testing.T) {
	cases := []struct {
		in     string
		want   string
		wantOK bool
	}{
		{"/Project/mdl/Acme/D-001.yaml.html", "/Project/mdl/Acme/D-001.yaml", true},
		{"/Project/ssr/Acme.yaml.html", "/Project/ssr/Acme.yaml", true},
		{"/Project/ssr/Acme.yaml", "/Project/ssr/Acme.yaml", false},
		{"/Project/ssr/form.html", "/Project/ssr/form.html", false},
	}
	for _, tc := range cases {
		got, ok := StripYAMLHTML(tc.in)
		if got != tc.want || ok != tc.wantOK {
			t.Errorf("%s: (%q, %v) want (%q, %v)", tc.in, got, ok, tc.want, tc.wantOK)
		}
	}
}

// ListParties reads the registry — one ssr/<party>.yaml per registered party.
func TestListParties(t *testing.T) {
	root := t.TempDir()
	projectAbs := filepath.Join(root, "Project")
	ssrDir := filepath.Join(projectAbs, "ssr")
	if err := os.MkdirAll(ssrDir, 0o755); err != nil {
		t.Fatal(err)
	}
	for _, party := range []string{"0330C1", "0440P2", "Acme"} {
		if err := os.WriteFile(filepath.Join(ssrDir, party+".yaml"), []byte("kind: SSR\n"), 0o644); err != nil {
			t.Fatal(err)
		}
	}
	// Non-.yaml files filtered out.
	_ = os.WriteFile(filepath.Join(ssrDir, "stray.txt"), []byte("x"), 0o644)

	parties, err := ListParties(projectAbs)
	if err != nil {
		t.Fatal(err)
	}
	if strings.Join(parties, ",") != "0330C1,0440P2,Acme" {
		t.Errorf("ListParties = %v, want [0330C1 0440P2 Acme]", parties)
	}
}

func TestListParties_NoRegistry(t *testing.T) {
	root := t.TempDir()
	parties, err := ListParties(filepath.Join(root, "Project"))
	if err != nil {
		t.Fatalf("err=%v want nil", err)
	}
	if len(parties) != 0 {
		t.Errorf("got %v, want empty", parties)
	}
}
