// static/shared/js/money.js
/**
 * Money handling utilities using integer cents.
 *
 * All monetary values are stored as integers representing cents in the database.
 * The API returns euros (converted from cents on the backend), but these utilities
 * can be used if cents are passed to the frontend.
 *
 * Example:
 *     105.91 EUR is stored as 10591 (integer cents)
 *
 * Usage:
 *     Money.format(10591)                    // Returns "105.91"
 *     Money.format(10591, 'EUR')             // Returns "105,91 EUR"
 *     Money.toCents(105.91)                  // Returns 10591
 *     Money.toEuros(10591)                   // Returns 105.91
 *     Money.formatEuros(105.91, 'EUR')       // Returns "105,91 EUR"
 *
 * See docs/architecture/money-handling.md for full documentation.
 */

const Money = {
    /**
     * Format cents as a currency string.
     *
     * @param {number} cents - Amount in cents
     * @param {string} currency - Currency code (default: '', no currency shown)
     * @param {string} locale - Locale for formatting (default: 'de-DE')
     * @returns {string} Formatted price string
     *
     * @example
     * Money.format(10591)           // "105.91"
     * Money.format(10591, 'EUR')    // "105,91 EUR" (German locale)
     * Money.format(1999)            // "19.99"
     */
    format(cents, currency = '', locale = 'de-DE') {
        if (cents === null || cents === undefined) {
            cents = 0;
        }

        const euros = cents / 100;

        if (currency) {
            return new Intl.NumberFormat(locale, {
                style: 'currency',
                currency: currency
            }).format(euros);
        }

        return new Intl.NumberFormat(locale, {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2
        }).format(euros);
    },

    /**
     * Convert euros to cents.
     *
     * @param {number|string} euros - Amount in euros
     * @returns {number} Amount in cents (integer)
     *
     * @example
     * Money.toCents(105.91)    // 10591
     * Money.toCents('19.99')   // 1999
     * Money.toCents(null)      // 0
     */
    toCents(euros) {
        if (euros === null || euros === undefined || euros === '') {
            return 0;
        }
        return Math.round(parseFloat(euros) * 100);
    },

    /**
     * Convert cents to euros.
     *
     * @param {number} cents - Amount in cents
     * @returns {number} Amount in euros
     *
     * @example
     * Money.toEuros(10591)    // 105.91
     * Money.toEuros(1999)     // 19.99
     * Money.toEuros(null)     // 0
     */
    toEuros(cents) {
        if (cents === null || cents === undefined) {
            return 0;
        }
        return cents / 100;
    },

    /**
     * Format a euro amount for display.
     *
     * Use this when the value is already in euros (e.g., from API response).
     *
     * @param {number} euros - Amount in euros
     * @param {string} currency - Currency code (default: 'EUR')
     * @param {string} locale - Locale for formatting (default: 'de-DE')
     * @returns {string} Formatted price string
     *
     * @example
     * Money.formatEuros(105.91, 'EUR')    // "105,91 EUR"
     * Money.formatEuros(19.99)            // "19.99"
     */
    formatEuros(euros, currency = '', locale = 'de-DE') {
        if (euros === null || euros === undefined) {
            euros = 0;
        }

        if (currency) {
            return new Intl.NumberFormat(locale, {
                style: 'currency',
                currency: currency
            }).format(euros);
        }

        return new Intl.NumberFormat(locale, {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2
        }).format(euros);
    },

    /**
     * Parse a price string to cents.
     *
     * Handles various formats:
     * - "19.99 EUR"
     * - "19,99"
     * - 19.99
     *
     * @param {string|number} priceStr - Price string or number
     * @returns {number} Amount in cents
     *
     * @example
     * Money.parse("19.99 EUR")    // 1999
     * Money.parse("19,99")        // 1999
     * Money.parse(19.99)          // 1999
     */
    parse(priceStr) {
        if (priceStr === null || priceStr === undefined || priceStr === '') {
            return 0;
        }

        if (typeof priceStr === 'number') {
            return Math.round(priceStr * 100);
        }

        // Remove currency symbols and spaces
        let cleaned = priceStr.toString().replace(/[^\d,.-]/g, '');

        // Handle European decimal comma
        cleaned = cleaned.replace(',', '.');

        try {
            return Math.round(parseFloat(cleaned) * 100);
        } catch {
            return 0;
        }
    },

    /**
     * Calculate line total (unit price * quantity).
     *
     * @param {number} unitPriceCents - Price per unit in cents
     * @param {number} quantity - Number of units
     * @returns {number} Total in cents
     */
    calculateLineTotal(unitPriceCents, quantity) {
        return unitPriceCents * quantity;
    },

    /**
     * Calculate order total.
     *
     * @param {number} subtotalCents - Sum of line items in cents
     * @param {number} taxCents - Tax amount in cents (default: 0)
     * @param {number} shippingCents - Shipping cost in cents (default: 0)
     * @param {number} discountCents - Discount amount in cents (default: 0)
     * @returns {number} Total in cents
     */
    calculateOrderTotal(subtotalCents, taxCents = 0, shippingCents = 0, discountCents = 0) {
        return subtotalCents + taxCents + shippingCents - discountCents;
    }
};

// Make available globally
window.Money = Money;

// Export for modules
if (typeof module !== 'undefined' && module.exports) {
    module.exports = Money;
}
