package user

import (
	"regexp"
	"strings"
)

const (
	// GlobalRegionCode 是没有命中任何显式国家映射时使用的兜底区域。
	GlobalRegionCode = "GLOBAL"

	// RegionStatusActive 表示区域映射参与国家到区域的实时解析。
	RegionStatusActive = "active"
	// RegionStatusDisabled 表示区域停止解析并释放 active 国家归属。
	RegionStatusDisabled = "disabled"

	// RegionRebuildTaskStatusPending 表示历史用户区域快照等待后台重算。
	RegionRebuildTaskStatusPending = "pending"
	// RegionRebuildTaskStatusRunning 表示任务已被某个 user-service 节点 claim。
	RegionRebuildTaskStatusRunning = "running"
	// RegionRebuildTaskStatusCompleted 表示该 country 下历史用户已经按任务 revision 重算完成。
	RegionRebuildTaskStatusCompleted = "completed"
	// RegionRebuildTaskStatusSkipped 表示任务 revision 已过期，不能覆盖更新映射。
	RegionRebuildTaskStatusSkipped = "skipped"
	// RegionRebuildTaskStatusFailed 表示任务处理失败，等待人工或后续重试策略处理。
	RegionRebuildTaskStatusFailed = "failed"
)

var (
	countryCodePattern           = regexp.MustCompile(`^[A-Z]{2,3}$`)
	isoAlpha3Pattern             = regexp.MustCompile(`^[A-Z]{3}$`)
	isoNumericPattern            = regexp.MustCompile(`^[0-9]{3}$`)
	phoneCountryCodePattern      = regexp.MustCompile(`^\+[1-9][0-9]{0,2}$`)
	shortRegionCodePattern       = regexp.MustCompile(`^[A-Za-z0-9_]{2,32}$`)
	descriptiveRegionCodePattern = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9 _-]{1,63}$`)
	retiredRegionCodes           = map[string]struct{}{
		"AUSTRALIA AND NEW ZEALAND": {},
		"CARIBBEAN":                 {},
		"MELANESIA":                 {},
		"MICRONESIA":                {},
		"POLYNESIA":                 {},
		"SOUTHERN AFRICA":           {},
		"UNSPECIFIED":               {},
	}
)

// Country 是国家主数据；enabled 是唯一可用性开关，外部只提交 CountryCode。
type Country struct {
	AppCode            string
	CountryID          int64
	CountryName        string
	CountryCode        string
	ISOAlpha3          string
	ISONumeric         string
	CountryDisplayName string
	PhoneCountryCode   string
	Flag               string
	Enabled            bool
	SortOrder          int32
	CreatedByUserID    int64
	UpdatedByUserID    int64
	CreatedAtMs        int64
	UpdatedAtMs        int64
}

// Region 是业务区域主数据；Countries 只放 active 国家码快照。
type Region struct {
	AppCode         string
	RegionID        int64
	RegionCode      string
	Name            string
	Status          string
	Countries       []string
	SortOrder       int32
	CreatedByUserID int64
	UpdatedByUserID int64
	CreatedAtMs     int64
	UpdatedAtMs     int64
}

// RegionCountryMapping 表示一个 active 或历史国家到区域归属记录。
type RegionCountryMapping struct {
	AppCode     string
	RegionID    int64
	CountryCode string
	Status      string
	CreatedAtMs int64
	UpdatedAtMs int64
}

// RegionChangeLog 是管理端区域配置审计，不记录用户隐私资料。
type RegionChangeLog struct {
	AppCode        string
	RegionID       int64
	Operation      string
	BeforeJSON     string
	AfterJSON      string
	OperatorUserID int64
	RequestID      string
	CreatedAtMs    int64
}

// UserRegionRebuildTask 表示按国家分页刷新 users.region_id 的后台任务。
type UserRegionRebuildTask struct {
	AppCode         string
	TaskID          int64
	RegionID        int64
	CountryCode     string
	TargetRegionID  int64
	MappingRevision int64
	Status          string
	CursorUserID    int64
	LockedBy        string
	LockedUntilMs   int64
	AttemptCount    int32
	ErrorMessage    string
	CreatedAtMs     int64
	UpdatedAtMs     int64
}

// RegionRebuildProcessResult 描述单次 worker 处理结果，便于测试和日志输出。
type RegionRebuildProcessResult struct {
	AppCode        string
	TaskID         int64
	CountryCode    string
	TargetRegionID int64
	Status         string
	ProcessedUsers int
	CursorUserID   int64
	NoTask         bool
}

// CountryFilter 描述国家管理列表过滤条件；国家只支持 enabled 维度过滤。
type CountryFilter struct {
	AppCode string
	Enabled *bool
}

// RegionFilter 描述区域管理列表过滤条件。
type RegionFilter struct {
	AppCode string
	Status  string
}

// UpdateCountryCommand 描述修改国家展示字段的事务输入，CountryCode 创建后不可变。
type UpdateCountryCommand struct {
	AppCode            string
	CountryID          int64
	CountryName        string
	ISOAlpha3          string
	ISONumeric         string
	CountryDisplayName string
	PhoneCountryCode   string
	Flag               string
	SortOrder          int32
	OperatorUserID     int64
	RequestID          string
	NowMs              int64
}

// UpdateRegionCommand 描述修改区域展示字段的事务输入，不修改 countries。
type UpdateRegionCommand struct {
	AppCode        string
	RegionID       int64
	RegionCode     string
	Name           string
	SortOrder      int32
	OperatorUserID int64
	RequestID      string
	NowMs          int64
}

// ReplaceRegionCountriesCommand 描述原子替换区域 active 国家归属的事务输入。
type ReplaceRegionCountriesCommand struct {
	AppCode        string
	RegionID       int64
	Countries      []string
	OperatorUserID int64
	RequestID      string
	NowMs          int64
}

// NormalizeCountryCode 统一客户端和管理端提交的国家码形态。
func NormalizeCountryCode(code string) string {
	return strings.ToUpper(strings.TrimSpace(code))
}

// ValidCountryCode 校验本系统允许的两到三位大写英文国家码。
func ValidCountryCode(code string) bool {
	return countryCodePattern.MatchString(code)
}

// NormalizeISOAlpha3 统一 ISO alpha-3 辅助展示字段形态；空值表示未配置。
func NormalizeISOAlpha3(code string) string {
	return strings.ToUpper(strings.TrimSpace(code))
}

// ValidISOAlpha3 校验非空 ISO alpha-3 或明确 user-assigned 三字码。
func ValidISOAlpha3(code string) bool {
	return code == "" || isoAlpha3Pattern.MatchString(code)
}

// NormalizeISONumeric 统一 ISO numeric/M49 字符串形态，不能转整数以免破坏前导零。
func NormalizeISONumeric(code string) string {
	return strings.TrimSpace(code)
}

// ValidISONumeric 校验非空 numeric 必须是三位数字字符串。
func ValidISONumeric(code string) bool {
	return code == "" || isoNumericPattern.MatchString(code)
}

// NormalizePhoneCountryCode 统一 E.164 国家呼叫码字段，空值表示无可用电话元数据。
func NormalizePhoneCountryCode(code string) string {
	return strings.TrimSpace(code)
}

// ValidPhoneCountryCode 校验国家呼叫码，不做唯一性假设，因为多个国家可以共享 +1。
func ValidPhoneCountryCode(code string) bool {
	return code == "" || phoneCountryCodePattern.MatchString(code)
}

// NormalizeRegionCode 统一区域业务编码形态。
func NormalizeRegionCode(code string) string {
	code = strings.TrimSpace(code)
	if shortRegionCodePattern.MatchString(code) {
		// 手工业务短码继续统一大写；导入的 subregion 描述码保留原始大小写和空格。
		return strings.ToUpper(code)
	}

	return strings.Join(strings.Fields(code), " ")
}

// ValidRegionCode 校验区域编码，避免自由文本进入唯一键和审计口径。
func ValidRegionCode(code string) bool {
	return shortRegionCodePattern.MatchString(code) || descriptiveRegionCodePattern.MatchString(code)
}

// IsGlobalRegionCode 判断区域是否是兜底 GLOBAL 区域。
func IsGlobalRegionCode(code string) bool {
	return NormalizeRegionCode(code) == GlobalRegionCode
}

// IsRetiredRegionCode 判断区域是否已从业务区域集合中移除。
func IsRetiredRegionCode(code string) bool {
	_, ok := retiredRegionCodes[strings.ToUpper(NormalizeRegionCode(code))]
	return ok
}
