// Package matcher 提供 nginx 风格的 location 匹配引擎实现。
//
// 该文件实现正则表达式匹配器，支持命名捕获组提取。
//
// 作者：xfy
package matcher

import (
	"regexp"

	"github.com/valyala/fasthttp"
)

// RegexMatcher 正则表达式匹配器。
//
// 使用 Go 标准库 regexp 编译正则模式，
// 支持命名捕获组提取，对应 nginx 的 ~ 和 ~* 修饰符。
type RegexMatcher struct {
	// pattern 编译后的正则表达式
	pattern *regexp.Regexp

	// handler 匹配成功后的请求处理器
	handler fasthttp.RequestHandler

	// captures 最后一次匹配提取的命名捕获组
	captures map[string]string

	// priority 匹配优先级，正则匹配为 3
	priority int

	// internal 是否为 internal location
	internal bool

	// caseInsensitive 是否大小写不敏感（~* 模式）
	caseInsensitive bool
}

// NewRegexMatcher 创建正则匹配器。
//
// 参数：
//   - pattern: 正则表达式模式字符串
//   - handler: 匹配成功后的请求处理器
//   - priority: 优先级（通常设为 3）
//   - caseInsensitive: 是否大小写不敏感
//   - internal: 是否为 internal location
//
// 返回值：
//   - *RegexMatcher: 正则匹配器实例
//   - error: 正则表达式编译失败时返回错误
func NewRegexMatcher(pattern string, handler fasthttp.RequestHandler, priority int, caseInsensitive bool, internal bool) (*RegexMatcher, error) {
	re, err := regexp.Compile(pattern)
	if err != nil {
		return nil, err
	}

	return &RegexMatcher{
		pattern:         re,
		handler:         handler,
		priority:        priority,
		caseInsensitive: caseInsensitive,
		internal:        internal,
		captures:        make(map[string]string),
	}, nil
}

// Match 检查路径是否匹配正则表达式。
//
// 参数：
//   - path: 待匹配的请求路径
//
// 返回值：
//   - bool: 正则匹配成功时返回 true
func (m *RegexMatcher) Match(path string) bool {
	return m.pattern.MatchString(path)
}

// Result 返回匹配结果。
//
// 返回值：
//   - *MatchResult: 包含处理器和匹配元数据的结果
func (m *RegexMatcher) Result() *MatchResult {
	locType := LocationTypeRegex
	if m.caseInsensitive {
		locType = LocationTypeRegexCaseless
	}
	return &MatchResult{
		Handler:      m.handler,
		Path:         m.pattern.String(),
		Priority:     m.priority,
		LocationType: locType,
		Captures:     m.captures,
		Internal:     m.internal,
	}
}

// GetCaptures 获取正则表达式在当前路径上的命名捕获组。
//
// 该方法在每次匹配后调用，提取捕获组数据供后续使用。
//
// 参数：
//   - path: 当前请求路径
//
// 返回值：
//   - map[string]string: 命名捕获组映射，无捕获时返回 nil
func (m *RegexMatcher) GetCaptures(path string) map[string]string {
	matches := m.pattern.FindStringSubmatch(path)
	if matches == nil {
		return nil
	}

	result := make(map[string]string)
	names := m.pattern.SubexpNames()
	for i, name := range names {
		if i == 0 {
			continue // 跳过全匹配（索引 0）
		}
		if name != "" && i < len(matches) {
			result[name] = matches[i]
		}
	}
	return result
}
