package tenancy

import (
	"fmt"
	"regexp"
	"strings"
)

const (
	FallbackReject   = "reject"
	FallbackUsername = "username"
	FallbackLiteral  = "literal"
)

// Resolver derives tenant IDs from CQL usernames.
type Resolver struct {
	regex        *regexp.Regexp
	fallback     string
	tenantIndex  int
	regexLiteral string
}

// NewResolver compiles the tenant regex and validates fallback behavior.
func NewResolver(pattern string, fallback string) (*Resolver, error) {
	if strings.TrimSpace(pattern) == "" {
		return nil, fmt.Errorf("tenant regex is required")
	}
	re, err := regexp.Compile(pattern)
	if err != nil {
		return nil, fmt.Errorf("invalid tenant regex: %w", err)
	}
	fallback = strings.ToLower(strings.TrimSpace(fallback))
	switch fallback {
	case "", FallbackUsername:
		fallback = FallbackUsername
	case FallbackReject, FallbackLiteral:
	default:
		return nil, fmt.Errorf("invalid tenant regex fallback %q", fallback)
	}

	tenantIndex := -1
	for i, name := range re.SubexpNames() {
		if name == "tenant" {
			tenantIndex = i
			break
		}
	}
	return &Resolver{
		regex:        re,
		fallback:     fallback,
		tenantIndex:  tenantIndex,
		regexLiteral: pattern,
	}, nil
}

// Resolve returns the tenant ID for a username.
func (r *Resolver) Resolve(username string) (string, error) {
	if r == nil || r.regex == nil {
		return "", fmt.Errorf("tenant resolver is not configured")
	}
	matches := r.regex.FindStringSubmatch(username)
	if len(matches) > 0 {
		if r.tenantIndex > 0 && r.tenantIndex < len(matches) {
			if matches[r.tenantIndex] != "" {
				return matches[r.tenantIndex], nil
			}
		}
		if len(matches) > 1 && matches[1] != "" {
			return matches[1], nil
		}
	}
	switch r.fallback {
	case FallbackReject:
		return "", fmt.Errorf("tenant regex did not match username")
	case FallbackLiteral:
		return r.regexLiteral, nil
	default:
		return username, nil
	}
}
