package util

import (
	"encoding/base64"
	"strings"
	"unicode"

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

// StringSegment 表示字符串片段及其类型
type StringSegment struct {
	Text    string
	StrType int // 0: 英文/数字, 1: 中文, 2: 其他语言
}

// SplitRuneString 将字符串切割成不同类型的片段
func SplitRuneString(s string) []StringSegment {
	var segments []StringSegment
	var builder strings.Builder
	var currentType int // 当前正在构建的片段类型

	// 获取字符类型
	getCharType := func(r rune) int {
		switch {
		case unicode.Is(unicode.Han, r):
			return 1 // 中文
		case unicode.Is(unicode.Hiragana, r) || unicode.Is(unicode.Katakana, r):
			return 2 // 日语假名
		case unicode.Is(unicode.Hangul, r):
			return 2 // 韩语
		case unicode.Is(unicode.Thai, r):
			return 2 // 泰语
		case unicode.IsLetter(r) || unicode.IsDigit(r):
			return 0 // 英文或数字
		default:
			// 其他 Unicode 字符，如果不是空格或标点，也认为是其他语言
			if !unicode.IsSpace(r) && !unicode.IsPunct(r) {
				return 2
			}
			// 对于空格和标点，跟随当前类型
			return currentType
		}
	}

	// 添加当前片段到结果中
	addSegment := func() {
		if builder.Len() > 0 {
			segments = append(segments, StringSegment{
				Text:    builder.String(),
				StrType: currentType,
			})
			builder.Reset()
		}
	}

	runes := []rune(s)
	if len(runes) == 0 {
		return segments
	}

	// 初始化第一个字符
	firstChar := runes[0]
	currentType = getCharType(firstChar)
	builder.WriteRune(firstChar)

	// 处理剩余字符
	for i := 1; i < len(runes); i++ {
		currentChar := runes[i]
		charType := getCharType(currentChar)

		// 如果字符类型发生变化，添加新片段
		if charType != currentType {
			addSegment()
			currentType = charType
		}

		builder.WriteRune(currentChar)
	}

	// 添加最后一个片段
	addSegment()

	return segments
}

// ConvertRuneToEn 将字符串中的中文转换为拼音，其他语言转换为 base64
func ConvertRuneToEn(s string) string {
	segments := SplitRuneString(s)
	var result strings.Builder
	a := pinyin.NewArgs()

	for i, seg := range segments {
		switch seg.StrType {
		case 0: // 英文/数字
			result.WriteString(seg.Text)
		case 1: // 中文
			pinyinSlice := pinyin.LazyPinyin(seg.Text, a)
			result.WriteString(strings.Join(pinyinSlice, ""))
		case 2: // 其他语言，使用 base64 编码（不带填充）
			result.WriteString(base64.RawURLEncoding.EncodeToString([]byte(seg.Text)))
		}

		// 如果不是最后一个片段，且下一个片段类型不同，添加空格
		if i < len(segments)-1 && segments[i+1].StrType != seg.StrType {
			result.WriteString("")
		}
	}
	return result.String()
}
