package currency

import (
	"fmt"
	"strings"
)

// Currency represents a currency with its details
type Currency struct {
	Code   string
	Name   string
	Symbol string
}

// SupportedCurrencies returns a list of supported currencies
func SupportedCurrencies() []Currency {
	return []Currency{
		{Code: "EUR", Name: "Euro", Symbol: "€"},
		{Code: "USD", Name: "US Dollar", Symbol: "$"},
		{Code: "GBP", Name: "British Pound", Symbol: "£"},
		{Code: "CHF", Name: "Swiss Franc", Symbol: "CHF"},
		{Code: "SEK", Name: "Swedish Krona", Symbol: "kr"},
		{Code: "NOK", Name: "Norwegian Krone", Symbol: "kr"},
		{Code: "DKK", Name: "Danish Krone", Symbol: "kr"},
		{Code: "PLN", Name: "Polish Zloty", Symbol: "zł"},
		{Code: "CZK", Name: "Czech Koruna", Symbol: "Kč"},
		{Code: "HUF", Name: "Hungarian Forint", Symbol: "Ft"},
		{Code: "CAD", Name: "Canadian Dollar", Symbol: "C$"},
		{Code: "AUD", Name: "Australian Dollar", Symbol: "A$"},
		{Code: "JPY", Name: "Japanese Yen", Symbol: "¥"},
		{Code: "CNY", Name: "Chinese Yuan", Symbol: "¥"},
		{Code: "RUB", Name: "Russian Ruble", Symbol: "₽"},
		{Code: "BRL", Name: "Brazilian Real", Symbol: "R$"},
		{Code: "MXN", Name: "Mexican Peso", Symbol: "$"},
		{Code: "INR", Name: "Indian Rupee", Symbol: "₹"},
		{Code: "KRW", Name: "South Korean Won", Symbol: "₩"},
		{Code: "SGD", Name: "Singapore Dollar", Symbol: "S$"},
		{Code: "HKD", Name: "Hong Kong Dollar", Symbol: "HK$"},
		{Code: "NZD", Name: "New Zealand Dollar", Symbol: "NZ$"},
		{Code: "ZAR", Name: "South African Rand", Symbol: "R"},
		{Code: "TRY", Name: "Turkish Lira", Symbol: "₺"},
		{Code: "ILS", Name: "Israeli Shekel", Symbol: "₪"},
	}
}

// GetCurrency returns a currency by its code
func GetCurrency(code string) (*Currency, bool) {
	code = strings.ToUpper(code)
	for _, currency := range SupportedCurrencies() {
		if currency.Code == code {
			return &currency, true
		}
	}
	return nil, false
}

// GetCurrencySymbol returns the symbol for a currency code
func GetCurrencySymbol(code string) string {
	if currency, exists := GetCurrency(code); exists {
		return currency.Symbol
	}
	return code // fallback to code if currency not found
}

// GetCurrencyName returns the name for a currency code
func GetCurrencyName(code string) string {
	if currency, exists := GetCurrency(code); exists {
		return currency.Name
	}
	return code // fallback to code if currency not found
}

// FormatPrice formats a price with the appropriate currency symbol
func FormatPrice(amount float64, currencyCode string) string {
	symbol := GetCurrencySymbol(currencyCode)

	// Handle currencies with different formatting conventions
	switch strings.ToUpper(currencyCode) {
	case "EUR", "GBP", "CHF":
		return fmt.Sprintf("%s%.2f", symbol, amount)
	case "USD", "CAD", "AUD", "HKD", "SGD", "NZD", "BRL", "MXN":
		return fmt.Sprintf("%s%.2f", symbol, amount)
	case "JPY", "KRW":
		// Yen and Won typically don't use decimal places
		return fmt.Sprintf("%s%.0f", symbol, amount)
	case "SEK", "NOK", "DKK":
		// Scandinavian currencies often put symbol after
		return fmt.Sprintf("%.2f %s", amount, symbol)
	case "PLN":
		return fmt.Sprintf("%.2f %s", amount, symbol)
	case "CZK":
		return fmt.Sprintf("%.2f %s", amount, symbol)
	case "HUF":
		return fmt.Sprintf("%.0f %s", amount, symbol)
	case "RUB":
		return fmt.Sprintf("%.2f %s", amount, symbol)
	case "INR":
		return fmt.Sprintf("%s%.2f", symbol, amount)
	case "CNY":
		return fmt.Sprintf("%s%.2f", symbol, amount)
	case "ZAR":
		return fmt.Sprintf("%s%.2f", symbol, amount)
	case "TRY":
		return fmt.Sprintf("%.2f %s", amount, symbol)
	case "ILS":
		return fmt.Sprintf("%s%.2f", symbol, amount)
	default:
		return fmt.Sprintf("%s%.2f", symbol, amount)
	}
}

// FormatPricePerLiter formats a price per liter with the appropriate currency symbol
func FormatPricePerLiter(amount float64, currencyCode string) string {
	symbol := GetCurrencySymbol(currencyCode)

	// Handle currencies with different formatting conventions
	switch strings.ToUpper(currencyCode) {
	case "EUR", "GBP", "CHF":
		return fmt.Sprintf("%s%.3f", symbol, amount)
	case "USD", "CAD", "AUD", "HKD", "SGD", "NZD", "BRL", "MXN":
		return fmt.Sprintf("%s%.3f", symbol, amount)
	case "JPY", "KRW":
		// Yen and Won typically don't use decimal places
		return fmt.Sprintf("%s%.0f", symbol, amount)
	case "SEK", "NOK", "DKK":
		return fmt.Sprintf("%.3f %s", amount, symbol)
	case "PLN":
		return fmt.Sprintf("%.3f %s", amount, symbol)
	case "CZK":
		return fmt.Sprintf("%.2f %s", amount, symbol)
	case "HUF":
		return fmt.Sprintf("%.0f %s", amount, symbol)
	case "RUB":
		return fmt.Sprintf("%.2f %s", amount, symbol)
	case "INR":
		return fmt.Sprintf("%s%.3f", symbol, amount)
	case "CNY":
		return fmt.Sprintf("%s%.3f", symbol, amount)
	case "ZAR":
		return fmt.Sprintf("%s%.3f", symbol, amount)
	case "TRY":
		return fmt.Sprintf("%.3f %s", amount, symbol)
	case "ILS":
		return fmt.Sprintf("%s%.3f", symbol, amount)
	default:
		return fmt.Sprintf("%s%.3f", symbol, amount)
	}
}

// IsValidCurrency checks if a currency code is supported
func IsValidCurrency(code string) bool {
	_, exists := GetCurrency(code)
	return exists
}

// GetDefaultCurrency returns the default currency
func GetDefaultCurrency() Currency {
	return Currency{Code: "EUR", Name: "Euro", Symbol: "€"}
}
