package util

import (
	"regexp"
	"strings"

	"github.com/mozillazg/go-pinyin"
)

// 图片命名生成器
type ImageNameGenerator struct {
	MaxLength       int    // 最大文件名长度（不含扩展名）
	Separator       string // 字段分隔符
	UseTimestamp    bool   // 是否使用时间戳
	TimestampFormat string // 时间戳格式
}

// 预编译正则表达式（性能优化）
var (
	// 匹配连续空格
	spaceRegex = regexp.MustCompile(`\s+`)
	// 匹配常见促销前缀（如：【现切果切】、【豪华果篮】等非核心信息）
	promoPrefixRegex = regexp.MustCompile(`^[【\[][^】\]]+[】\]]`)
	// 匹配促销后缀（如：限时折扣、买一送一等）
	promoSuffixRegex = regexp.MustCompile(`(限时折扣|特价|促销|优惠|秒杀|买.*送.*|赠品|礼盒装|套装|活动|包邮|含税|整件|酸甜|默认切好|默认开小口)$`)
	// 匹配括号内促销内容和规格外的括号内容
	promoInParenthesesRegex = regexp.MustCompile(`[(（][^)）]*?(促销|优惠|活动|新品|限时|特价|随机搭配|整果|默认|整件|酸甜|天然|纯木本植物原汁|随机)[^)）]*?[)）]|[(（][^)）]*?(约|左右|箱|个|件|盒|罐|瓶|毫升|斤|克|g|G)[^)）]*?[)）]`)
	// 匹配特殊字符（保留中文、英文、数字、空格及核心符号：/+-_.()）
	specialCharsRegex = regexp.MustCompile(`[^\p{Han}a-zA-Z0-9\s/+-_.()]`)
)

// fullWidthToHalfWidth 将全角字符转换为半角字符
// 用于统一字符宽度，确保后续文本处理（如正则匹配）的一致性
// 参数：
//
//	s - 可能包含全角字符的字符串
//
// 返回值：
//
//	转换为半角字符后的字符串
func fullWidthToHalfWidth(s string) string {
	result := make([]rune, 0, len(s))
	for _, r := range s {
		if r >= 65281 && r <= 65374 {
			// 全角字符（除空格）转换为半角
			result = append(result, r-65248)
		} else if r == 12288 {
			// 全角空格转换为半角空格
			result = append(result, 32)
		} else {
			// 其他字符保持不变
			result = append(result, r)
		}
	}
	return string(result)
}

// CleanProductName 清洗商品名称
// CleanProductName 清理电商商品标题，保留核心名称（品牌+产品名+规格）
// 遵循美团/京东/天猫规则：移除促销信息、营销话术、平台标识，保留商品本质特征
// 参数：
//
//	name - 原始商品标题
//
// 返回值：
//
//	清理后的商品核心名称
func CleanProductName(name string) string {
	// 1. 全角转半角（优先统一字符宽度，避免后续正则匹配问题）
	name = fullWidthToHalfWidth(name)

	// 2. 移除常见促销前缀（如：【旗舰店】、【2023新款】等非核心信息）
	name = promoPrefixRegex.ReplaceAllString(name, "")

	// 3. 移除促销后缀（如：限时折扣、买一送一等）
	name = promoSuffixRegex.ReplaceAllString(name, "")

	// 4. 移除括号内促销内容（保留括号外核心信息）
	// 例：小米11(新品上市) → 小米11；iPhone 13(128G/黑色) → iPhone 13(128G/黑色)（保留规格）
	name = promoInParenthesesRegex.ReplaceAllString(name, "")

	// 5. 移除特殊字符（保留中文、英文、数字、空格及核心符号：/+-_.()）
	name = specialCharsRegex.ReplaceAllString(name, "")

	// 6. 标准化空格（多个空格→单个空格，首尾空格去除）
	name = spaceRegex.ReplaceAllString(name, " ")
	name = strings.TrimSpace(name)

	// 7. 移除重复品牌词（如：小米小米11 → 小米11）
	if brand := extractBrand(name); brand != "" {
		// 使用非贪婪匹配确保只替换开头的重复品牌词
		name = regexp.MustCompile(`^`+regexp.QuoteMeta(brand)+`{2,}`).ReplaceAllString(name, brand)
	}

	return name
}

// CleanProductForFilePath 清理商品名称以适应Linux文件路径规则
// 将斜杠替换为空格，其他不允许的字符替换为下划线，并确保路径安全
func CleanProductForFilePath(name string) string {
	// 清除空格
	name = strings.ReplaceAll(name, " ", "")
	// 将斜杠替换为空字符串
	name = strings.ReplaceAll(name, "/", "")

	// 替换Linux文件系统不允许的特殊字符
	invalidChars := `[\:*?"<>|]`
	regex := regexp.MustCompile(invalidChars)
	name = regex.ReplaceAllString(name, "")

	// 移除连续下划线
	regex = regexp.MustCompile(`_+`)
	name = regex.ReplaceAllString(name, "")

	return strings.Trim(name, "_")
}

// 中文转拼音
// ChineseToPinyin 将中文转换为拼音（无声调）
// 用于生成符合文件系统命名规范的名称
// 参数：
//
//	s - 包含中文的字符串
//
// 返回值：
//
//	转换后的拼音字符串
func ChineseToPinyin(s string) string {
	args := pinyin.NewArgs()
	args.Style = pinyin.Normal // 普通风格，不带声调
	return strings.Join(pinyin.LazyConvert(s, &args), "")
}

// ExtractKeywords 从商品名称中提取关键词
// 用于图片命名时获取核心识别信息
// 参数：
//
//	name - 清理后的商品名称
//	limit - 最大关键词数量
//
// 返回值：
//
//	提取的关键词列表
func ExtractKeywords(name string, limit int) []string {
	words := strings.Fields(name)
	if len(words) > limit {
		return words[:limit]
	}
	return words
}

// SanitizeFileName 规范化文件名
// 移除操作系统不允许的特殊字符，确保文件名合法
// 参数：
//
//	name - 原始文件名
//
// 返回值：
//
//	安全的文件名
func SanitizeFileName(name string) string {
	// 移除Linux不允许的字符
	invalidChars := `[\/:*?"<>|]`
	regex := regexp.MustCompile(invalidChars)
	name = regex.ReplaceAllString(name, "_")

	// 移除连续下划线
	regex = regexp.MustCompile(`_+`)
	name = regex.ReplaceAllString(name, "_")

	return strings.Trim(name, "_")
}

// extractBrand 提取商品品牌（用于去重处理）
// 从商品名称开头提取已知品牌，支持中英文品牌名
// 参数：
//
//	name - 清理后的商品名称
//
// 返回值：
//
//	提取到的品牌名，若未匹配则返回空字符串
func extractBrand(name string) string {
	// 常见品牌词库（可根据业务需求扩展）
	brands := []string{"小米", "华为", "苹果", "iPhone", "三星", "OPPO", "vivo", "荣耀", "realme", "红米", "魅族"}
	for _, b := range brands {
		if strings.HasPrefix(name, b) {
			return b
		}
	}
	return ""
}
