package dialectsfcrm

import (
	"fmt"
	"strings"
)

type currencyDisplayFormatter struct{}

func NewCurrencyDisplayFormatter() currencyDisplayFormatter {
	return currencyDisplayFormatter{}
}

func (currencyDisplayFormatter) FormatCurrencyDisplayValue(value float64, currencyISOCode string) string {
	code := normalizeCurrencyISOCode(currencyISOCode)
	decimals := 2
	prefix := ""
	if code != "" {
		prefix = code + " "
	}
	switch code {
	case "USD":
		prefix = "$"
	case "JPY":
		prefix = "¥"
		decimals = 0
	case "CNY":
		prefix = "¥"
	case "SGD":
		prefix = "S$"
	}
	return prefix + formatCurrencyAmount(value, decimals)
}

func normalizeCurrencyISOCode(raw string) string {
	code := strings.ToUpper(strings.TrimSpace(raw))
	if len(code) != 3 {
		return ""
	}
	for _, r := range code {
		if r < 'A' || r > 'Z' {
			return ""
		}
	}
	return code
}

func formatCurrencyAmount(value float64, decimals int) string {
	sign := ""
	if value < 0 {
		sign = "-"
		value = -value
	}

	formatted := fmt.Sprintf("%.*f", decimals, value)
	integerPart := formatted
	fractionalPart := ""
	if dot := strings.IndexByte(formatted, '.'); dot >= 0 {
		integerPart = formatted[:dot]
		fractionalPart = formatted[dot:]
	}

	if len(integerPart) <= 3 {
		return sign + integerPart + fractionalPart
	}

	var grouped []byte
	firstGroupLen := len(integerPart) % 3
	if firstGroupLen == 0 {
		firstGroupLen = 3
	}
	grouped = append(grouped, integerPart[:firstGroupLen]...)
	for i := firstGroupLen; i < len(integerPart); i += 3 {
		grouped = append(grouped, ',')
		grouped = append(grouped, integerPart[i:i+3]...)
	}
	return sign + string(grouped) + fractionalPart
}
