package route

import (
	"regexp"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestPrefixMatcher(t *testing.T) {
	tests := []struct {
		name       string
		prefix     string
		path       string
		wantMatch  bool
		wantRemain string
	}{
		{
			name:       "exact match",
			prefix:     "/pd",
			path:       "/pd",
			wantMatch:  true,
			wantRemain: "",
		},
		{
			name:       "prefix match with remaining",
			prefix:     "/pd",
			path:       "/pd/api/v1",
			wantMatch:  true,
			wantRemain: "/api/v1",
		},
		{
			name:      "no match",
			prefix:    "/pd",
			path:      "/tikv/api",
			wantMatch: false,
		},
		{
			name:      "partial prefix does not match",
			prefix:    "/pd",
			path:      "/pdb/api",
			wantMatch: false,
		},
		{
			name:       "empty prefix matches all",
			prefix:     "",
			path:       "/any/path",
			wantMatch:  true,
			wantRemain: "/any/path",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			m := NewPrefixMatcher(tt.prefix)
			result := m.Match(tt.path)

			assert.Equal(t, tt.wantMatch, result.Matched)
			if tt.wantMatch {
				assert.Equal(t, tt.wantRemain, result.Remaining)
			}
		})
	}
}

func TestRegexMatcher(t *testing.T) {
	tests := []struct {
		name       string
		pattern    string
		paramNames []string
		path       string
		wantMatch  bool
		wantParams map[string]string
		wantRemain string
	}{
		{
			name:       "single param match",
			pattern:    `^/tibr/([^/]+)(/.*)?$`,
			paramNames: []string{"tibr_id"},
			path:       "/tibr/12345/api/v1",
			wantMatch:  true,
			wantParams: map[string]string{"tibr_id": "12345"},
			wantRemain: "/api/v1",
		},
		{
			name:       "single param no remaining",
			pattern:    `^/tibr/([^/]+)(/.*)?$`,
			paramNames: []string{"tibr_id"},
			path:       "/tibr/12345",
			wantMatch:  true,
			wantParams: map[string]string{"tibr_id": "12345"},
			wantRemain: "",
		},
		{
			name:       "multiple params",
			pattern:    `^/cluster/([^/]+)/service/([^/]+)(/.*)?$`,
			paramNames: []string{"cluster_id", "service_name"},
			path:       "/cluster/abc/service/pd/status",
			wantMatch:  true,
			wantParams: map[string]string{"cluster_id": "abc", "service_name": "pd"},
			wantRemain: "/status",
		},
		{
			name:       "no match",
			pattern:    `^/tibr/([^/]+)(/.*)?$`,
			paramNames: []string{"tibr_id"},
			path:       "/pd/api",
			wantMatch:  false,
		},
		{
			name:       "no params - static regex",
			pattern:    `^/static(/.*)?$`,
			paramNames: []string{},
			path:       "/static/file.txt",
			wantMatch:  true,
			wantParams: nil,
			wantRemain: "/file.txt",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			re := regexp.MustCompile(tt.pattern)
			m := NewRegexMatcher(re, tt.paramNames)
			result := m.Match(tt.path)

			assert.Equal(t, tt.wantMatch, result.Matched)
			if tt.wantMatch {
				assert.Equal(t, tt.wantParams, result.PathParams)
				assert.Equal(t, tt.wantRemain, result.Remaining)
			}
		})
	}
}
