package domain

import (
	"errors"
	"strings"
	"unicode"
)

var hanmacSurnameRomanization = map[rune]string{
	'한': "han",
	'김': "kim",
	'이': "lee",
	'박': "park",
	'최': "choi",
	'정': "jung",
	'조': "cho",
	'강': "kang",
	'윤': "yoon",
	'장': "jang",
	'임': "lim",
	'림': "lim",
	'신': "shin",
	'오': "oh",
	'서': "seo",
	'권': "kwon",
	'황': "hwang",
	'안': "ahn",
	'송': "song",
	'전': "jeon",
	'홍': "hong",
	'유': "yoo",
	'고': "ko",
	'문': "moon",
	'양': "yang",
	'손': "son",
	'배': "bae",
	'백': "baek",
	'허': "heo",
	'남': "nam",
	'심': "sim",
	'노': "noh",
	'하': "ha",
	'곽': "kwak",
	'성': "sung",
	'차': "cha",
	'주': "joo",
	'우': "woo",
	'구': "koo",
	'민': "min",
	'류': "ryu",
	'나': "na",
	'진': "jin",
	'지': "ji",
	'엄': "um",
	'채': "chae",
	'원': "won",
	'천': "cheon",
	'방': "bang",
	'공': "gong",
	'현': "hyun",
	'함': "ham",
	'여': "yeo",
	'추': "choo",
	'도': "do",
	'소': "so",
	'석': "seok",
	'선': "sun",
	'설': "seol",
	'마': "ma",
	'길': "gil",
	'연': "yeon",
	'위': "wi",
	'표': "pyo",
	'명': "myung",
	'기': "ki",
	'반': "ban",
	'라': "ra",
	'왕': "wang",
	'금': "geum",
	'옥': "ok",
	'육': "yook",
	'인': "in",
	'맹': "maeng",
	'제': "je",
	'모': "mo",
	'탁': "tak",
	'국': "guk",
	'어': "eo",
	'은': "eun",
	'편': "pyeon",
	'용': "yong",
}

var hanmacInitialRomanization = []string{
	"g", "g", "n", "d", "d", "r", "m", "b", "b", "s",
	"s", "y", "j", "j", "c", "k", "t", "p", "h",
}

func SplitEmailDomain(email string) (string, string, error) {
	normalized := strings.ToLower(strings.TrimSpace(email))
	before, after, ok := strings.Cut(normalized, "@")
	if !ok {
		return "", "", errors.New("email must contain @")
	}
	if strings.Count(normalized, "@") != 1 {
		return "", "", errors.New("email must contain one @")
	}
	localPart := strings.TrimSpace(before)
	domainPart := strings.TrimSpace(after)
	if domainPart == "" || !strings.Contains(domainPart, ".") {
		return "", "", errors.New("email domain is invalid")
	}
	return localPart, domainPart, nil
}

func ExtractNormalizedEmailLocalPart(email string) (string, error) {
	localPart, _, err := SplitEmailDomain(email)
	if err != nil {
		return "", err
	}
	if localPart == "" {
		return "", errors.New("email local-part is empty")
	}
	return localPart, nil
}

func BuildKoreanNameEmailBase(name string) (string, bool, error) {
	runes := compactNameRunes(name)
	if len(runes) < 2 {
		return "", true, nil
	}

	surname, ok := hanmacSurnameRomanization[runes[0]]
	if !ok {
		return "", true, nil
	}

	var builder strings.Builder
	for _, r := range runes[1:] {
		initial, ok := romanizedHangulInitial(r)
		if !ok {
			return "", true, nil
		}
		builder.WriteString(initial)
	}
	builder.WriteString(surname)
	return builder.String(), false, nil
}

func MatchesSuggestedNameRule(localPart string, base string) bool {
	localPart = strings.ToLower(strings.TrimSpace(localPart))
	base = strings.ToLower(strings.TrimSpace(base))
	if localPart == "" || base == "" {
		return false
	}
	if localPart == base {
		return true
	}
	if !strings.HasPrefix(localPart, base) {
		return false
	}
	suffix := localPart[len(base):]
	if suffix == "" {
		return false
	}
	for _, r := range suffix {
		if r < '0' || r > '9' {
			return false
		}
	}
	return true
}

func compactNameRunes(name string) []rune {
	var runes []rune
	for _, r := range strings.TrimSpace(name) {
		if unicode.IsSpace(r) {
			continue
		}
		runes = append(runes, r)
	}
	return runes
}

func romanizedHangulInitial(r rune) (string, bool) {
	const hangulBase = 0xAC00
	const hangulEnd = 0xD7A3
	if r < hangulBase || r > hangulEnd {
		return "", false
	}
	index := int(r-hangulBase) / 588
	if index < 0 || index >= len(hanmacInitialRomanization) {
		return "", false
	}
	return hanmacInitialRomanization[index], true
}
