package discovery

import "strings"

var knownRails = map[string]struct{}{
	RailCrypto:             {},
	RailProviderSettlement: {},
	RailLedger:             {},
	RailCardPayout:         {},
	RailFiatOnRamp:         {},
}

var knownRailOperations = map[string]struct{}{
	RailOperationDebit:          {},
	RailOperationCredit:         {},
	RailOperationExternalDebit:  {},
	RailOperationExternalCredit: {},
	RailOperationMove:           {},
	RailOperationSend:           {},
	RailOperationFee:            {},
	RailOperationObserveConfirm: {},
	RailOperationFXConvert:      {},
	RailOperationBlock:          {},
	RailOperationRelease:        {},
}

// NormalizeRail canonicalizes a rail token.
func NormalizeRail(value string) string {
	clean := strings.ToUpper(strings.TrimSpace(value))
	if clean == "" {
		return ""
	}
	clean = strings.ReplaceAll(clean, "-", "_")
	clean = strings.ReplaceAll(clean, " ", "_")
	for strings.Contains(clean, "__") {
		clean = strings.ReplaceAll(clean, "__", "_")
	}
	return clean
}

// IsKnownRail reports whether the value is a recognized payment rail.
func IsKnownRail(value string) bool {
	_, ok := knownRails[NormalizeRail(value)]
	return ok
}

// NormalizeRailOperation canonicalizes a rail operation token.
func NormalizeRailOperation(value string) string {
	return strings.ToUpper(strings.TrimSpace(value))
}

// IsKnownRailOperation reports whether the value is a recognized rail operation.
func IsKnownRailOperation(value string) bool {
	_, ok := knownRailOperations[NormalizeRailOperation(value)]
	return ok
}

// ExpandRailOperation maps canonical and legacy names to normalized rail operations.
func ExpandRailOperation(value string) []string {
	if op := NormalizeRailOperation(value); op != "" {
		if IsKnownRailOperation(op) {
			return []string{op}
		}
	}

	switch strings.ToLower(strings.TrimSpace(value)) {
	case OperationExternalDebit:
		return []string{RailOperationExternalDebit}
	case OperationExternalCredit:
		return []string{RailOperationExternalCredit}
	case OperationFee:
		return []string{RailOperationFee}
	case OperationObserveConfirm:
		return []string{RailOperationObserveConfirm}
	case OperationFXConvert:
		return []string{RailOperationFXConvert}
	default:
		return nil
	}
}

// NormalizeRailOperations canonicalizes and deduplicates rail operation values.
func NormalizeRailOperations(values []string) []string {
	if len(values) == 0 {
		return nil
	}

	result := make([]string, 0, len(values))
	seen := map[string]bool{}
	for _, value := range values {
		for _, op := range ExpandRailOperation(value) {
			if op == "" || seen[op] {
				continue
			}
			seen[op] = true
			result = append(result, op)
		}
	}
	if len(result) == 0 {
		return nil
	}
	return result
}

// CryptoRailGatewayOperations returns canonical operations for crypto rail gateways.
func CryptoRailGatewayOperations() []string {
	return []string{
		OperationBalanceRead,
		OperationSend,
		OperationExternalDebit,
		OperationExternalCredit,
		OperationFee,
		OperationObserveConfirm,
	}
}

// CardPayoutRailGatewayOperations returns canonical operations for card payout gateways.
func CardPayoutRailGatewayOperations() []string {
	return []string{
		OperationSend,
		OperationExternalCredit,
		OperationObserveConfirm,
	}
}

// ProviderSettlementRailGatewayOperations returns canonical operations for settlement gateways.
func ProviderSettlementRailGatewayOperations() []string {
	return []string{
		OperationFXConvert,
		OperationObserveConfirm,
	}
}
