package identity

import (
	"strings"
	"testing"

	userdomain "hyapp/services/user-service/internal/domain/user"
)

func TestGenerateAABBCCCandidates(t *testing.T) {
	t.Parallel()

	candidates := generateAABBCCCandidates()
	if len(candidates) != 1000 {
		t.Fatalf("candidate count = %d, want 1000", len(candidates))
	}

	seen := make(map[string]struct{}, len(candidates))
	for _, candidate := range candidates {
		if len(candidate) != 6 {
			t.Fatalf("candidate %q length = %d, want 6", candidate, len(candidate))
		}
		if candidate[0] != candidate[1] || candidate[2] != candidate[3] || candidate[4] != candidate[5] {
			t.Fatalf("candidate %q does not match AABBCC", candidate)
		}
		if _, ok := seen[candidate]; ok {
			t.Fatalf("candidate %q is duplicated", candidate)
		}
		seen[candidate] = struct{}{}
	}
}

func TestGeneratePrettyDisplayIDCandidatesForMarketRules(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name     string
		ruleType string
		want     []string
	}{
		{name: "repeat 4A", ruleType: userdomain.PrettyDisplayIDRuleAAAA, want: []string{"0000", "1111", "2222"}},
		{name: "ABAB", ruleType: userdomain.PrettyDisplayIDRuleABAB, want: []string{"0101", "0202", "0303"}},
		{name: "ABBA", ruleType: userdomain.PrettyDisplayIDRuleABBA, want: []string{"0110", "0220", "0330"}},
		{name: "ascending", ruleType: userdomain.PrettyDisplayIDRuleABCD, want: []string{"0123", "1234", "2345"}},
		{name: "descending", ruleType: userdomain.PrettyDisplayIDRuleDCBA, want: []string{"3210", "4321", "5432"}},
		{name: "ABCABC", ruleType: userdomain.PrettyDisplayIDRuleABCABC, want: []string{"012012", "123123", "234234"}},
		{name: "love", ruleType: userdomain.PrettyDisplayIDRuleLove, want: []string{"520", "521", "1314"}},
	}

	for _, tc := range tests {
		tc := tc
		t.Run(tc.name, func(t *testing.T) {
			t.Parallel()

			candidates, err := generatePrettyDisplayIDCandidates(tc.ruleType, "")
			if err != nil {
				t.Fatalf("generate candidates failed: %v", err)
			}
			for index, want := range tc.want {
				if candidates[index] != want {
					t.Fatalf("candidate[%d] = %q, want %q", index, candidates[index], want)
				}
			}
		})
	}
}

func TestGeneratePrettyDisplayIDCandidatesWithConfig(t *testing.T) {
	t.Parallel()

	candidates, err := generatePrettyDisplayIDCandidates(userdomain.PrettyDisplayIDRuleAABB, `{"digits":["6","8","9"],"exclude_digits":["9"],"prefix":"VIP"}`)
	if err != nil {
		t.Fatalf("generate candidates failed: %v", err)
	}
	if strings.Join(candidates, ",") != "VIP6688,VIP8866" {
		t.Fatalf("candidates = %#v", candidates)
	}

	custom, err := generatePrettyDisplayIDCandidates(userdomain.PrettyDisplayIDRuleCustomValues, `{"values":["VIP2026","ملك123","VIP!"]}`)
	if err != nil {
		t.Fatalf("generate custom candidates failed: %v", err)
	}
	if strings.Join(custom, ",") != "VIP2026,ملك123,VIP!" {
		t.Fatalf("custom candidates = %#v", custom)
	}
}

func TestGenerateDatePrettyDisplayIDCandidates(t *testing.T) {
	t.Parallel()

	candidates, err := generatePrettyDisplayIDCandidates(userdomain.PrettyDisplayIDRuleDateYYYYMMDD, `{"start_date":"2026-06-09","end_date":"2026-06-11"}`)
	if err != nil {
		t.Fatalf("generate date candidates failed: %v", err)
	}
	if strings.Join(candidates, ",") != "20260609,20260610,20260611" {
		t.Fatalf("date candidates = %#v", candidates)
	}
}
