/**
 * Currency Service - XMR/Fiat Conversion
 * 
 * Uses CoinGecko API for real-time exchange rates (CORS-friendly)
 * Supports two modes: fiat-fix and xmr-fix
 */

const COINGECKO_API = 'https://api.coingecko.com/api/v3/simple/price'

const CURRENCY_SYMBOLS = {
    XMR: 'ɱ',
    EUR: '€',
    USD: '$',
    GBP: '£',
    CHF: 'CHF',
    JPY: '¥',
    RUB: '₽',
    BRL: 'R$'
}

const CACHE_DURATION = 60 * 60 * 1000 // 60 minutes (CoinGecko free tier is strict)
const MIN_REQUEST_INTERVAL = 120 * 1000 // 2 minutes between requests
const STORAGE_KEY = 'xmr_rates_cache'

let cachedRates = null
let cacheTimestamp = 0
let lastRequestTime = 0
let pendingRequest = null

// Load from localStorage on init
function loadFromStorage() {
    try {
        const stored = localStorage.getItem(STORAGE_KEY)
        if (stored) {
            const { rates, timestamp } = JSON.parse(stored)
            if (rates && timestamp && Date.now() - timestamp < CACHE_DURATION) {
                cachedRates = rates
                cacheTimestamp = timestamp
            }
        }
    } catch (e) {
        // Ignore storage errors
    }
}

function saveToStorage() {
    try {
        localStorage.setItem(STORAGE_KEY, JSON.stringify({
            rates: cachedRates,
            timestamp: cacheTimestamp
        }))
    } catch (e) {
        // Ignore storage errors
    }
}

loadFromStorage()

/**
 * Fetches current XMR rates from CoinGecko with rate limiting
 * @returns {Promise<Object>} Rates per currency (e.g. { EUR: 329.05, USD: 388.87 })
 */
export async function getXmrRates() {
    // Return cached rates if still valid
    if (cachedRates && Date.now() - cacheTimestamp < CACHE_DURATION) {
        return cachedRates
    }

    // If a request is already pending, wait for it
    if (pendingRequest) {
        return pendingRequest
    }

    // Rate limiting: ensure minimum interval between requests
    const timeSinceLastRequest = Date.now() - lastRequestTime
    if (timeSinceLastRequest < MIN_REQUEST_INTERVAL && cachedRates) {
        return cachedRates
    }

    // Create and store the pending request
    pendingRequest = fetchRates()
    
    try {
        const rates = await pendingRequest
        return rates
    } finally {
        pendingRequest = null
    }
}

async function fetchRates() {
    lastRequestTime = Date.now()
    
    try {
        const currencies = 'eur,usd,gbp,chf,jpy,rub,brl'
        const response = await fetch(`${COINGECKO_API}?ids=monero&vs_currencies=${currencies}`)
        
        // Handle rate limit response
        if (response.status === 429) {
            console.warn('CoinGecko rate limit hit, using cached rates')
            return cachedRates || getDefaultRates()
        }
        
        const data = await response.json()

        if (!data.monero) {
            console.error('CoinGecko API Error: No data returned')
            return cachedRates || getDefaultRates()
        }

        const rates = {
            EUR: data.monero.eur,
            USD: data.monero.usd,
            GBP: data.monero.gbp,
            CHF: data.monero.chf,
            JPY: data.monero.jpy,
            RUB: data.monero.rub,
            BRL: data.monero.brl
        }

        // Update cache
        cachedRates = rates
        cacheTimestamp = Date.now()
        saveToStorage()

        return rates
    } catch (error) {
        console.error('Failed to fetch XMR rates:', error)
        return cachedRates || getDefaultRates()
    }
}

/**
 * Fallback rates if API is unreachable
 */
function getDefaultRates() {
    return {
        EUR: 150,
        USD: 165,
        GBP: 130,
        CHF: 145,
        JPY: 24000,
        RUB: 15000,
        BRL: 850
    }
}

/**
 * Converts amount to XMR
 * @param {number} amount - Amount in source currency
 * @param {string} currency - Source currency (EUR, USD, etc.)
 * @param {Object} rates - Rates from getXmrRates()
 * @returns {number} Amount in XMR
 */
export function convertToXmr(amount, currency, rates) {
    if (currency === 'XMR') return amount
    if (!rates[currency]) return amount
    return amount / rates[currency]
}

/**
 * Converts XMR to fiat
 * @param {number} xmrAmount - Amount in XMR
 * @param {string} currency - Target currency (EUR, USD, etc.)
 * @param {Object} rates - Rates from getXmrRates()
 * @returns {number} Amount in target currency
 */
export function convertFromXmr(xmrAmount, currency, rates) {
    if (currency === 'XMR') return xmrAmount
    if (!rates[currency]) return xmrAmount
    return xmrAmount * rates[currency]
}

/**
 * Converts between fiat currencies using XMR as bridge
 * @param {number} amount - Amount in source currency
 * @param {string} fromCurrency - Source currency
 * @param {string} toCurrency - Target currency
 * @param {Object} rates - Rates from getXmrRates() (XMR -> Fiat)
 * @returns {number} Amount in target currency
 */
export function convertFiat(amount, fromCurrency, toCurrency, rates) {
    if (fromCurrency === toCurrency) return amount
    if (!rates[fromCurrency] || !rates[toCurrency]) return amount
    
    // Use XMR as bridge: EUR -> XMR -> USD
    // 1 XMR = rates[EUR] EUR, so 1 EUR = 1/rates[EUR] XMR
    // 1 XMR = rates[USD] USD
    // Therefore: 1 EUR = rates[USD] / rates[EUR] USD
    return amount * (rates[toCurrency] / rates[fromCurrency])
}

/**
 * Get user's preferred display currency from settings
 * @returns {string} Currency code (default: 'USD')
 */
export function getDisplayCurrency() {
    return localStorage.getItem('dgray_currency') || 'USD'
}

/**
 * Formats a price for display
 * Shows price in user's preferred currency with XMR equivalent
 * @param {Object} listing - Listing with price, currency, price_mode
 * @param {Object} rates - Rates from getXmrRates()
 * @param {string} [displayCurrency] - Override display currency
 * @returns {Object} { primary, secondary, xmrAmount }
 */
export function formatPrice(listing, rates, displayCurrency = null) {
    const { price, currency, price_mode } = listing
    const userCurrency = displayCurrency || getDisplayCurrency()

    if (!price || price === 0) {
        return {
            primary: 'Free',
            secondary: null,
            xmrAmount: 0
        }
    }

    // XMR mode: XMR is the reference price
    if (price_mode === 'xmr' || currency === 'XMR') {
        const xmrPrice = currency === 'XMR' ? price : convertToXmr(price, currency, rates)
        const fiatEquivalent = convertFromXmr(xmrPrice, userCurrency, rates)

        return {
            primary: formatFiat(fiatEquivalent, userCurrency),
            secondary: `≈ ${formatXmr(xmrPrice)}`,
            xmrAmount: xmrPrice
        }
    }

    // Fiat mode: Convert to user's preferred currency
    const xmrEquivalent = convertToXmr(price, currency, rates)
    
    // Always show in user's currency as primary
    const displayPrice = userCurrency === currency 
        ? price 
        : convertFiat(price, currency, userCurrency, rates)

    return {
        primary: formatFiat(displayPrice, userCurrency),
        secondary: `≈ ${formatXmr(xmrEquivalent)}`,
        xmrAmount: xmrEquivalent
    }
}

/**
 * Formats XMR amount
 * @param {number} amount - Amount in XMR
 * @returns {string} Formatted string (e.g. "0.5234 XMR")
 */
export function formatXmr(amount) {
    if (amount >= 1) {
        return `${amount.toFixed(4)} XMR`
    }
    return `${amount.toFixed(6)} XMR`
}

/**
 * Formats fiat amount
 * @param {number} amount - Amount
 * @param {string} currency - Currency
 * @returns {string} Formatted string (e.g. "€ 150,00")
 */
export function formatFiat(amount, currency) {
    const symbol = CURRENCY_SYMBOLS[currency] || currency
    
    const formatted = new Intl.NumberFormat('de-DE', {
        minimumFractionDigits: 2,
        maximumFractionDigits: 2
    }).format(amount)

    // Symbol before or after amount
    if (['EUR', 'GBP', 'USD', 'BRL'].includes(currency)) {
        return `${symbol} ${formatted}`
    }
    return `${formatted} ${symbol}`
}

/**
 * Returns the currency symbol
 * @param {string} currency - Currency code
 * @returns {string} Symbol
 */
export function getCurrencySymbol(currency) {
    return CURRENCY_SYMBOLS[currency] || currency
}

/**
 * List of supported currencies
 */
export const SUPPORTED_CURRENCIES = ['XMR', 'EUR', 'CHF', 'USD', 'GBP', 'JPY', 'RUB', 'BRL']

export default {
    getXmrRates,
    getDisplayCurrency,
    convertToXmr,
    convertFromXmr,
    convertFiat,
    formatPrice,
    formatXmr,
    formatFiat,
    getCurrencySymbol,
    SUPPORTED_CURRENCIES
}
