package util

// 【使用例子：】
// func main() {
// 	cleaner := NewTitleCleaner()

// 	// 测试用例（包含特殊字符）
// 	testCases := []string{
// 		"【限时优惠】苹果 iPhone 14 Pro 256G 金色！",
// 		"耐克官方旗舰店 Air Max 270 男子运动鞋/黑/白",
// 		"(新品) 立白洗洁精500g*2瓶*促销装",
// 		"美团优选 山东红富士苹果 5斤装@新鲜水果",
// 		"盒马鲜生 智利车厘子 500g#特级",
// 		"钱大妈 土猪肉 五花肉 500g$新鲜现切",
// 		"大希地 西冷牛排 200g*4片%原切",
// 		"鲁花花生油 5L&压榨一级",
// 		"三只松鼠 碧根果 200g*袋装",
// 		"Samsung Galaxy S23 Ultra 256GB*Phantom Black",
// 	}

// 	for _, title := range testCases {
// 		cleaned := cleaner.Clean(title)
// 		productName := cleaner.ExtractProductName(cleaned)
// 		spec := cleaner.ExtractSpec(cleaned)
// 		safeFileName := cleaner.CleanForFileName(title)

// 		fmt.Printf("原始标题: %s\n", title)
// 		fmt.Printf("清洗后: %s\n", cleaned)
// 		fmt.Printf("商品名称: %s\n", productName)
// 		fmt.Printf("规格: %s\n", spec)
// 		fmt.Printf("安全文件名: %s\n\n", safeFileName)
// 	}

// 	// 自定义保留符号示例
// 	cleaner.SetFileNameSafeSymbols("-_. ")
// 	fmt.Println("自定义保留符号后的处理:")
// 	fmt.Printf("安全文件名: %s\n", cleaner.CleanForFileName("华为 MateBook 14s+16GB/512G@银"))
// }

// 原始标题: 【限时优惠】苹果 iPhone 14 Pro 256G 金色！
// 清洗后: iPhone 14 Pro 256G 金色
// 商品名称: iPhone 14 Pro 金色
// 规格: 256G
// 安全文件名: iPhone 14 Pro 256G 金色

// 原始标题: 耐克官方旗舰店 Air Max 270 男子运动鞋/黑/白
// 清洗后: Air Max 270 男子运动鞋 黑/白
// 商品名称: Air Max 270 男子运动鞋
// 规格:
// 安全文件名: Air Max 270 男子运动鞋 黑 白

// 原始标题: (新品) 立白洗洁精500g*2瓶*促销装
// 清洗后: 洗洁精500g*2瓶
// 商品名称: 洗洁精
// 规格: 500g 2瓶
// 安全文件名: 立白洗洁精500g 2瓶

// 原始标题: 美团优选 山东红富士苹果 5斤装@新鲜水果
// 清洗后: 红富士苹果 5斤装
// 商品名称: 红富士苹果
// 规格: 5斤
// 安全文件名: 红富士苹果 5斤装

// 原始标题: 盒马鲜生 智利车厘子 500g#特级
// 清洗后: 车厘子 500g
// 商品名称: 车厘子
// 规格: 500g
// 安全文件名: 车厘子 500g

// 原始标题: 钱大妈 土猪肉 五花肉 500g$新鲜现切
// 清洗后: 五花肉 500g
// 商品名称: 五花肉
// 规格: 500g
// 安全文件名: 土猪肉 五花肉 500g

// 原始标题: 大希地 西冷牛排 200g*4片%原切
// 清洗后: 西冷牛排 200g*4片
// 商品名称: 西冷牛排
// 规格: 200g 4片
// 安全文件名: 大希地 西冷牛排 200g 4片

// 原始标题: 鲁花花生油 5L&压榨一级
// 清洗后: 花生油 5L
// 商品名称: 花生油
// 规格: 5L
// 安全文件名: 鲁花花生油 5L

// 原始标题: 三只松鼠 碧根果 200g*袋装
// 清洗后: 碧根果 200g
// 商品名称: 碧根果
// 规格: 200g
// 安全文件名: 三只松鼠 碧根果 200g

// 原始标题: Samsung Galaxy S23 Ultra 256GB*Phantom Black
// 清洗后: Galaxy S23 Ultra 256GB Phantom Black
// 商品名称: Galaxy S23 Ultra Phantom Black
// 规格: 256GB
// 安全文件名: Samsung Galaxy S23 Ultra 256GB Phantom Black

// 自定义保留符号后的处理:
// 安全文件名: 华为 MateBook 14s+16GB_512G 银

import (
	"regexp"
	"strings"
)

// 商品标题清洗器
type TitleCleaner struct {
	// 促销词列表
	promotionWords []string
	// 店铺类型列表
	shopTypes []string
	// 品牌名列表（支持多语言）
	brands map[string]bool
	// 规格单位列表
	specUnits map[string]bool
	// 地域词列表
	regions map[string]bool
	// 生鲜品类词列表
	freshCategories map[string]bool
	// 文件名非法字符正则（匹配Windows和Linux均不允许的字符）
	reInvalidFileNameChars *regexp.Regexp
	// 数字匹配正则
	reDigits *regexp.Regexp
	// 其他正则表达式缓存
	reBrackets      *regexp.Regexp
	reSymbols       *regexp.Regexp
	reSpaces        *regexp.Regexp
	reLeadingBrands *regexp.Regexp
	reSpecPatterns  []*regexp.Regexp
	reFreshPatterns []*regexp.Regexp
}

// 创建新的标题清洗器
func NewTitleCleaner() *TitleCleaner {
	cleaner := &TitleCleaner{
		promotionWords: []string{
			"限时优惠", "特价", "促销", "折扣", "满减", "秒杀", "包邮", "热卖", "新品",
			"特惠", "赠礼", "活动", "爆款", "超值", "福利", "限时", "疯抢", "清仓",
			"特价", "大促", "满赠", "限时购", "季末清仓", "限时秒杀", "狂欢价",
			"券后", "折后", "今日特惠", "限时价", "会员价", "新客价", "新人专享",
			"立减", "直降", "低价", "惊爆价", "冰点价", "吐血价", "大酬宾", "大甩卖",
			"超值套餐", "组合优惠", "套装", "礼盒装", "多件优惠", "买一送一", "第二件半价",
			"for sale", "discount", "special offer", "promotion", "limited time", "free shipping",
			"new arrival", "hot deal", "best price", "flash sale", "bundle", "gift with purchase",
		},
		shopTypes: []string{
			"旗舰店", "专卖店", "专营店", "官方店", "自营店", "直销店",
			"工厂店", "折扣店", "品牌店", "授权店", "精品店", "加盟店",
			"体验店", "便利店", "超市", "卖场", "商城", "全球购", "海外购",
			"进口", "直营", "官方", "官方授权", "授权", "官方旗舰店",
			"store", "shop", "official", "authorized", "boutique", "premium",
			"outlet", "factory", "online", "global", "international", "生鲜", "果蔬", "食品",
		},
		brands:                 make(map[string]bool),
		specUnits:              make(map[string]bool),
		regions:                make(map[string]bool),
		freshCategories:        make(map[string]bool),
		reInvalidFileNameChars: regexp.MustCompile(`[\\/:*?"<>|]`), // Windows/Linux均禁止的字符
		reDigits:               regexp.MustCompile(`\d+`),
		reBrackets:             regexp.MustCompile(`\([^)]*\)|\[[^]]*]|<[^>]*>|\{[^}]*\}|（[^）]*）|【[^】]*】|〔[^〕]*〕`),
		reSymbols:              regexp.MustCompile(`[^\p{Han}\p{Latin}0-9xX*×+\-*/\\\s]`),
		reSpaces:               regexp.MustCompile(`\s+`),
		reLeadingBrands:        regexp.MustCompile(`^[\p{Han}\p{Latin}0-9]+[、\s\-:：]*`),
		reSpecPatterns: []*regexp.Regexp{
			regexp.MustCompile(`\d+[a-zA-Z]+`),          // 数字+单位，如500ml
			regexp.MustCompile(`\d+[xX*×]\d+`),          // 数字x数字，如10x20
			regexp.MustCompile(`\d+[xX*×]\d+[xX*×]\d+`), // 三维尺寸，如10x20x30
			regexp.MustCompile(`\d+[+\-*/]\d+`),         // 数字+运算符+数字，如12+3
			regexp.MustCompile(`\d+\.\d+[a-zA-Z]+`),     // 小数+单位，如3.5kg
			regexp.MustCompile(`\d+\.\d+`),              // 纯小数，如3.5
			regexp.MustCompile(`\d+/\d+`),               // 分数，如1/2
			regexp.MustCompile(`\d+[件盒瓶包箱袋支个只袋卷罐片粒包本张套斤两克千克升毫升箱组台袋条根把捆盒箱罐桶份袋枚]`), // 中文数量单位
			regexp.MustCompile(`\d+[a-zA-Z]+/\d+[a-zA-Z]+`), // 复合单位，如500ml/瓶
			regexp.MustCompile(`\d+[a-zA-Z]+[a-zA-Z]+`),     // 数字+单位复数，如10grams
			regexp.MustCompile(`\d+[a-zA-Z]*\s+[a-zA-Z]+`),  // 数字+空格+单位，如10 pieces
			regexp.MustCompile(`\d+[至到]\d+[a-zA-Z]+`),       // 范围表示，如10-20kg
			regexp.MustCompile(`\d+[至到]\d+[件盒瓶包箱袋支个只袋卷罐片粒包本张套斤两克千克升毫升箱组台]`), // 中文范围
		},
		reFreshPatterns: []*regexp.Regexp{
			regexp.MustCompile(`[\p{Han}]+[肉禽蛋鱼海鲜果蔬粮油][\p{Han}]*`), // 生鲜品类识别
			regexp.MustCompile(`[\p{Han}]+[果菜菇豆稻麦米][\p{Han}]*`),    // 果蔬品类识别
			regexp.MustCompile(`[\p{Han}]+[猪牛羊鸡鱼虾蟹][\p{Han}]*`),    // 肉类识别
		},
	}

	// 添加国内常见品牌
	cleaner.AddBrands([]string{
		"苹果", "华为", "小米", "三星", "耐克", "阿迪达斯", "可口可乐", "立白", "海尔",
		"美的", "格力", "五粮液", "茅台", "旺旺", "伊利", "蒙牛", "宝洁", "联合利华",
		"双汇", "雨润", "三全", "思念", "太太乐", "王守义", "老干妈", "海天", "李锦记",
		"娃哈哈", "康师傅", "统一", "农夫山泉", "蒙牛", "伊利", "光明", "旺旺", "达利园",
		"三只松鼠", "良品铺子", "百草味", "来伊份", "海底捞", "好丽友", "雀巢", "奥利奥",
		"乐事", "可比克", "喜之郎", "旺旺", "大白兔", "冠生园", "梅林", "王守义", "乌江",
		"洽洽", "溜溜梅", "有友", "卫龙", "良品铺子", "三只松鼠", "獐子岛", "北大荒",
		"阳澄湖", "恒顺", "太太乐", "加加", "李锦记", "鲁花", "金龙鱼", "福临门", "海天",
	})

	// 添加生鲜、食品类品牌
	cleaner.AddBrands([]string{
		"獐子岛", "正大", "大希地", "恒都", "科尔沁", "皓月", "钱大妈", "盒马", "山姆",
		"沃尔玛", "永辉", "家乐福", "麦德龙", "大润发", "物美", "华润万家", "百果园",
		"鲜丰水果", "绿叶水果", "每日优鲜", "叮咚买菜", "美团优选", "淘菜菜", "多多买菜",
		"海底捞", "德庄", "桥头", "好人家", "天味", "鹃城牌", "饭扫光", "李锦记", "海天",
		"鲁花", "金龙鱼", "福临门", "太太乐", "王守义", "老干妈", "乌江", "涪陵", "有友",
	})

	// 添加常见规格单位（增强生鲜类）
	cleaner.AddSpecUnits([]string{
		"g", "kg", "mg", "ml", "l", "oz", "lb", "cm", "mm", "m", "inch", "ft",
		"件", "盒", "瓶", "包", "箱", "袋", "支", "个", "只", "卷", "罐", "片", "粒", "包", "本", "张", "套", "斤", "两",
		"kg", "g", "ml", "l", "cm", "m", "mm", "inch", "ft", "yd", "oz", "lb",
		"kilo", "gram", "milliliter", "liter", "centimeter", "meter", "millimeter",
		"inch", "foot", "yard", "ounce", "pound", "pack", "box", "case", "bottle",
		"piece", "set", "dozen", "pair", "sheet", "roll", "bag", "carton", "portion",
		"份", "枚", "条", "根", "把", "捆", "簇", "串", "头", "尾", "块", "朵", "颗", "株",
	})

	// 添加常见地域词
	cleaner.AddRegions([]string{
		"山东", "泰国", "进口", "国产", "美国", "日本", "韩国", "欧洲", "澳洲", "新西兰",
		"made in usa", "made in japan", "imported", "海外", "全球", "本地", "有机", "无公害",
		"绿色", "生态", "天然", "野生", "养殖", "散养", "土生", "本地", "农家", "原生态",
	})

	// 添加生鲜品类词
	cleaner.AddFreshCategories([]string{
		"蔬菜", "水果", "肉类", "海鲜", "水产", "粮油", "干货", "禽蛋", "奶制品", "速冻",
		"猪", "牛", "羊", "鸡", "鸭", "鹅", "鱼", "虾", "蟹", "贝", "蛋", "奶", "豆",
		"苹果", "香蕉", "橙子", "梨", "葡萄", "草莓", "西瓜", "哈密瓜", "芒果", "菠萝",
		"白菜", "萝卜", "土豆", "西红柿", "黄瓜", "茄子", "辣椒", "豆角", "洋葱", "大蒜",
		"猪肉", "牛肉", "羊肉", "鸡肉", "鸭肉", "鱼肉", "虾肉", "蟹肉", "贝肉", "鸡蛋", "鸭蛋",
	})

	return cleaner
}

// 添加品牌到清洗器
func (c *TitleCleaner) AddBrand(brand string) {
	c.brands[strings.ToLower(normalizeString(brand))] = true
}

// 批量添加品牌
func (c *TitleCleaner) AddBrands(brands []string) {
	for _, brand := range brands {
		c.AddBrand(brand)
	}
}

// 添加规格单位
func (c *TitleCleaner) AddSpecUnit(unit string) {
	c.specUnits[strings.ToLower(unit)] = true
}

// 批量添加规格单位
func (c *TitleCleaner) AddSpecUnits(units []string) {
	for _, unit := range units {
		c.AddSpecUnit(unit)
	}
}

// 添加地域词
func (c *TitleCleaner) AddRegion(region string) {
	c.regions[strings.ToLower(normalizeString(region))] = true
}

// 批量添加地域词
func (c *TitleCleaner) AddRegions(regions []string) {
	for _, region := range regions {
		c.AddRegion(region)
	}
}

// 添加生鲜品类词
func (c *TitleCleaner) AddFreshCategory(category string) {
	c.freshCategories[strings.ToLower(normalizeString(category))] = true
}

// 批量添加生鲜品类词
func (c *TitleCleaner) AddFreshCategories(categories []string) {
	for _, category := range categories {
		c.AddFreshCategory(category)
	}
}

// 清洗商品标题（移除冗余信息，保留核心内容）
func (c *TitleCleaner) Clean(title string) string {
	// 0. 字符串标准化（处理特殊字符和大小写）
	originalTitle := title
	title = normalizeString(title)

	// 1. 去除括号及内部内容
	title = c.reBrackets.ReplaceAllString(title, "")

	// 2. 去除常见促销词
	for _, word := range c.promotionWords {
		word = normalizeString(word)
		title = strings.ReplaceAll(title, word, "")
	}

	// 3. 去除店铺类型标识
	for _, shopType := range c.shopTypes {
		shopType = normalizeString(shopType)
		title = strings.ReplaceAll(title, shopType, "")
	}

	// 4. 去除地域词
	words := strings.Fields(title)
	for _, word := range words {
		wordLower := strings.ToLower(word)
		if c.regions[wordLower] {
			title = strings.ReplaceAll(title, word, "")
		}
	}

	// 5. 处理品牌名（保留品牌名，不做移除处理）
	// 注释掉品牌名移除逻辑，以保留品牌信息
	/*
		words = strings.Fields(title)
		if len(words) > 0 {
			firstWord := strings.ToLower(words[0])
			if c.brands[firstWord] {
				// 移除开头的品牌名
				title = strings.TrimSpace(strings.TrimPrefix(title, words[0]))
			} else if len(words) > 1 {
				// 尝试匹配多词品牌
				twoWordBrand := strings.ToLower(words[0] + " " + words[1])
				if c.brands[twoWordBrand] {
					title = strings.TrimSpace(strings.TrimPrefix(title, words[0]+" "+words[1]))
				}
			}
		}
	*/

	// 6. 处理生鲜品类词（注释掉以保留核心名称中的品类信息）
	/*
		words = strings.Fields(title)
		if len(words) > 0 {
			firstWord := strings.ToLower(words[0])
			if c.freshCategories[firstWord] {
				// 移除开头的品类词
				title = strings.TrimSpace(strings.TrimPrefix(title, words[0]))
			}
		}
	*/

	// 7. 移除多余符号，保留规格相关符号（如数字、小数点、单位等）
	title = c.reSymbols.ReplaceAllString(title, "")

	// 8. 合并连续空格
	title = c.reSpaces.ReplaceAllString(title, " ")

	// 9. 去除首尾空格
	title = strings.TrimSpace(title)

	// 10. 特殊处理：如果清洗后标题为空，返回原始标题的简化版
	if title == "" {
		title = normalizeString(originalTitle)
		title = c.reBrackets.ReplaceAllString(title, "")
		title = c.reSymbols.ReplaceAllString(title, "")
		title = c.reSpaces.ReplaceAllString(title, " ")
		title = strings.TrimSpace(title)
	}

	return title
}

// 提取规格信息
func (c *TitleCleaner) ExtractSpec(title string) string {
	var specs []string

	// 先尝试使用正则表达式匹配
	for _, re := range c.reSpecPatterns {
		specs = append(specs, re.FindAllString(title, -1)...)
	}

	// 再尝试识别数字+单位的组合
	words := strings.Fields(title)
	for i, word := range words {
		if c.reDigits.MatchString(word) {
			// 数字后面可能跟着单位
			if i+1 < len(words) {
				nextWord := strings.ToLower(words[i+1])
				if c.specUnits[nextWord] {
					specs = append(specs, word+" "+nextWord)
				}
			}

			// 检查数字和字母组合的单位
			reUnit := regexp.MustCompile(`(\d+)([a-zA-Z]+)`)
			if reUnit.MatchString(word) {
				matches := reUnit.FindStringSubmatch(word)
				if len(matches) == 3 {
					unit := strings.ToLower(matches[2])
					if c.specUnits[unit] {
						specs = append(specs, word)
					}
				}
			}

			// 检查范围表示，如"10-20kg"
			reRange := regexp.MustCompile(`(\d+)([至到])(\d+)([a-zA-Z]+)`)
			if reRange.MatchString(word) {
				specs = append(specs, word)
			}
		}
	}

	return strings.Join(unique(specs), " ")
}

// 提取核心商品名称
func (c *TitleCleaner) ExtractProductName(title string) string {
	spec := c.ExtractSpec(title)
	if spec == "" {
		return title
	}

	// 从标题中移除规格部分
	re := regexp.MustCompile(regexp.QuoteMeta(spec))
	name := re.ReplaceAllString(title, "")

	// 清理剩余的空格和符号
	name = strings.TrimSpace(name)
	name = regexp.MustCompile(`\s+`).ReplaceAllString(name, " ")

	return name
}

// 仅清理不符合文件命名规范的特殊字符，保留所有原始信息
func (c *TitleCleaner) CleanForFileName(originalTitle string) string {
	// 1. 删除所有非法字符（Windows/Linux均禁止的字符：\/:*?"<>|）
	safeTitle := c.reInvalidFileNameChars.ReplaceAllString(originalTitle, "")

	// 2. 删除所有空格
	safeTitle = regexp.MustCompile(`\s+`).ReplaceAllString(safeTitle, "")

	// 3. 移除尾部点号（Windows不允许文件名以点结尾）
	safeTitle = strings.TrimRight(safeTitle, ".")

	// 4. 限制文件名长度（Windows最大255字符，Linux最大255字节）
	if len(safeTitle) > 255 {
		safeTitle = safeTitle[:255]
	}

	return safeTitle
}

// 字符串标准化（处理特殊字符和大小写）
func normalizeString(s string) string {
	// 转换为小写
	s = strings.ToLower(s)

	// 处理特殊字符
	s = strings.ReplaceAll(s, "™", "")
	s = strings.ReplaceAll(s, "®", "")
	s = strings.ReplaceAll(s, "©", "")

	// 处理全角字符
	s = strings.Map(func(r rune) rune {
		if r >= '！' && r <= '～' {
			// 全角字符转换为半角
			return r - 0xfee0
		}
		return r
	}, s)

	return s
}

// 去重
func unique(strs []string) []string {
	keys := make(map[string]bool)
	list := []string{}
	for _, entry := range strs {
		if _, exists := keys[entry]; !exists {
			keys[entry] = true
			list = append(list, entry)
		}
	}
	return list
}
