import { i18n } from '../i18n.js'

const POW_SERVER = 'https://pow.dgray.io'

let modalScriptLoaded = false
let modalScriptLoading = null

/**
 * Load BTCPay modal checkout script once
 */
async function ensureModalLoaded() {
    if (modalScriptLoaded) return
    if (modalScriptLoading) return modalScriptLoading

    modalScriptLoading = new Promise((resolve, reject) => {
        const script = document.createElement('script')
        script.src = 'https://pay.xmr.rocks/modal/btcpay.js'
        script.onload = () => {
            modalScriptLoaded = true
            resolve()
        }
        script.onerror = () => reject(new Error('Failed to load BTCPay checkout'))
        document.head.appendChild(script)
    })

    return modalScriptLoading
}

/**
 * Create a payment invoice for a listing
 * @param {string} listingId - The listing UUID
 * @param {string} [currency='EUR'] - Payment currency
 * @returns {Promise<Object>} { invoiceId, checkoutLink, status, expirationTime }
 */
export async function createInvoice(listingId, currency = 'EUR') {
    const response = await fetch(`${POW_SERVER}/btcpay/invoice`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ listingId, currency })
    })

    if (!response.ok) {
        const error = await response.json().catch(() => ({}))
        throw new Error(error.error || 'Failed to create invoice')
    }

    return response.json()
}

/**
 * Check invoice payment status
 * @param {string} invoiceId
 * @returns {Promise<Object>} { invoiceId, status, additionalStatus }
 */
export async function getInvoiceStatus(invoiceId) {
    const response = await fetch(`${POW_SERVER}/btcpay/status?id=${encodeURIComponent(invoiceId)}`)

    if (!response.ok) {
        const error = await response.json().catch(() => ({}))
        throw new Error(error.error || 'Failed to check invoice status')
    }

    return response.json()
}

/**
 * Open the BTCPay modal checkout
 * @param {string} invoiceId
 * @returns {Promise<string>} Final status when modal closes
 */
export async function openCheckout(invoiceId) {
    await ensureModalLoaded()

    return new Promise((resolve) => {
        let lastStatus = null

        window.btcpay.onModalReceiveMessage((msg) => {
            if (msg?.status) lastStatus = msg.status
        })

        window.btcpay.onModalWillLeave(() => {
            resolve(lastStatus || 'unknown')
        })

        const lang = i18n.getLocale() || 'en'
        window.btcpay.showInvoice(invoiceId, { lang })
    })
}

/**
 * Poll invoice status until settled, expired, or timeout
 * @param {string} invoiceId
 * @param {Object} [options]
 * @param {number} [options.interval=4000] - Poll interval in ms
 * @param {number} [options.timeout=900000] - Timeout in ms (default 15min)
 * @param {Function} [options.onUpdate] - Callback on status change
 * @returns {Promise<Object>} Final status object
 */
export async function pollUntilDone(invoiceId, options = {}) {
    const {
        interval = 4000,
        timeout = 900000,
        onUpdate = null
    } = options

    const startTime = Date.now()
    let lastStatus = null

    while (Date.now() - startTime < timeout) {
        const result = await getInvoiceStatus(invoiceId)

        if (result.status !== lastStatus) {
            lastStatus = result.status
            if (onUpdate) onUpdate(result)
        }

        if (['Settled', 'Expired', 'Invalid'].includes(result.status)) {
            return result
        }

        await new Promise(r => setTimeout(r, interval))
    }

    throw new Error('Payment check timed out')
}

/**
 * Check if a listing has a pending invoice stored locally
 * @param {string} listingId
 * @returns {Object|null} { invoiceId, createdAt }
 */
export function getPendingInvoice(listingId) {
    try {
        const data = localStorage.getItem(`dgray_invoice_${listingId}`)
        return data ? JSON.parse(data) : null
    } catch (e) {
        return null
    }
}

/**
 * Store a pending invoice reference locally
 * @param {string} listingId
 * @param {string} invoiceId
 */
export function savePendingInvoice(listingId, invoiceId) {
    try {
        localStorage.setItem(`dgray_invoice_${listingId}`, JSON.stringify({
            invoiceId,
            createdAt: Date.now()
        }))
    } catch (e) {
        // Storage unavailable
    }
}

/**
 * Remove pending invoice reference
 * @param {string} listingId
 */
export function clearPendingInvoice(listingId) {
    localStorage.removeItem(`dgray_invoice_${listingId}`)
}

export default {
    createInvoice,
    getInvoiceStatus,
    openCheckout,
    pollUntilDone,
    getPendingInvoice,
    savePendingInvoice,
    clearPendingInvoice
}
