package award

import "strings"

// WPXPrefix is the exported entry point for deriving a callsign's CQ WPX prefix
// (used by contest-mode multiplier counting).
func WPXPrefix(call string) string { return wpxPrefix(call) }

// wpxPrefix derives the CQ WPX prefix from a callsign. This is an approximation
// of the official WPX rules — good enough to count distinct prefixes worked:
//   - standard call: letters+digits up to and including the LAST digit of the
//     first group (F4BPO→F4, EA8ABC→EA8, 9A1AA→9A1, OH2BH→OH2)
//   - no digit: first two letters + "0" (RAEM→RA0)
//   - portable "A/B": a short alpha(+digit) segment is treated as the prefix
//     designator; a lone-digit segment replaces the call's digit (F4BPO/9→F9)
func wpxPrefix(call string) string {
	c := strings.ToUpper(strings.TrimSpace(call))
	if c == "" {
		return ""
	}
	if strings.Contains(c, "/") {
		return portablePrefix(c)
	}
	return standardPrefix(c)
}

func portablePrefix(c string) string {
	parts := strings.Split(c, "/")
	// Drop pure operating-modifier suffixes.
	kept := make([]string, 0, len(parts))
	for _, p := range parts {
		switch p {
		case "P", "M", "MM", "AM", "QRP", "A", "R", "B", "LH":
			continue
		}
		if p != "" {
			kept = append(kept, p)
		}
	}
	if len(kept) == 0 {
		kept = parts
	}
	// Pick a base = the longest segment (the actual call).
	base := kept[0]
	for _, p := range kept[1:] {
		if len(p) > len(base) {
			base = p
		}
	}
	for _, p := range kept {
		if p == base {
			continue
		}
		if isAllDigits(p) {
			// Lone digit replaces the call's region digit: F4BPO/9 → F9.
			return replaceLastDigit(standardPrefix(base), p)
		}
		if len(p) <= 4 && hasLetter(p) {
			// Prefix designator wins: VP8/F4BPO → VP8 (+digit if missing).
			return ensureTrailingDigit(p)
		}
	}
	return standardPrefix(base)
}

// standardPrefix applies the basic WPX rule to a plain callsign: the prefix is
// the call up to and including its last digit (9A1AA→9A1, EA8ABC→EA8). Standard
// callsigns carry no digit in the suffix, so "last digit" is the prefix digit.
func standardPrefix(c string) string {
	lastDigit := -1
	for i := 0; i < len(c); i++ {
		if c[i] >= '0' && c[i] <= '9' {
			lastDigit = i
		}
	}
	if lastDigit < 0 {
		// No digit at all: first two letters + 0.
		if len(c) >= 2 {
			return c[:2] + "0"
		}
		return c + "0"
	}
	return c[:lastDigit+1]
}

func ensureTrailingDigit(p string) string {
	for i := 0; i < len(p); i++ {
		if p[i] >= '0' && p[i] <= '9' {
			return p
		}
	}
	return p + "0"
}

func replaceLastDigit(prefix, digit string) string {
	for i := len(prefix) - 1; i >= 0; i-- {
		if prefix[i] >= '0' && prefix[i] <= '9' {
			return prefix[:i] + digit
		}
	}
	return prefix + digit
}

func isAllDigits(s string) bool {
	if s == "" {
		return false
	}
	for i := 0; i < len(s); i++ {
		if s[i] < '0' || s[i] > '9' {
			return false
		}
	}
	return true
}

func hasLetter(s string) bool {
	for i := 0; i < len(s); i++ {
		if (s[i] >= 'A' && s[i] <= 'Z') || (s[i] >= 'a' && s[i] <= 'z') {
			return true
		}
	}
	return false
}
