/**
 * PaymentProvider — module-local state, fully independent from the app's global
 * mockStore so the Payments module can be added/removed in isolation.
 *
 * Transaction history is sourced from two places and merged by id:
 *   1. The server (api/payments/transactions → Vercel KV, written by the
 *      webhook) — the production source of truth.
 *   2. A local record (localStorage) written when a customer returns to the
 *      success page — gives instant feedback and works without KV in the demo.
 */

import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
import { INVOICES } from '../data/invoices';
import { stripeConfig } from '../config/stripeConfig';

const STORAGE_KEY = 'lynkeduppro.payments.transactions';

const loadLocal = () => {
    try {
        const raw = localStorage.getItem(STORAGE_KEY);
        return raw ? JSON.parse(raw) : [];
    } catch {
        return [];
    }
};

const persistLocal = (txns) => {
    try {
        localStorage.setItem(STORAGE_KEY, JSON.stringify(txns));
    } catch {
        /* localStorage unavailable (private mode) — keep in-memory only. */
    }
};

const mergeById = (a, b) => {
    const map = new Map();
    [...a, ...b].forEach((t) => {
        if (t && t.id) map.set(t.id, { ...map.get(t.id), ...t });
    });
    return Array.from(map.values()).sort(
        (x, y) => new Date(y.createdAt || 0) - new Date(x.createdAt || 0)
    );
};

const PaymentContext = createContext(null);

export const PaymentProvider = ({ children }) => {
    const [invoices] = useState(INVOICES);
    const [transactions, setTransactions] = useState(loadLocal);

    // Pull the server-side (webhook-written) history and merge it in.
    useEffect(() => {
        let cancelled = false;
        (async () => {
            try {
                const res = await fetch(`${stripeConfig.apiBase}/transactions`);
                if (!res.ok) return;
                const { transactions: server = [] } = await res.json();
                if (cancelled || !server.length) return;
                setTransactions((prev) => mergeById(prev, server));
            } catch {
                /* offline / endpoint unavailable — local history is fine. */
            }
        })();
        return () => {
            cancelled = true;
        };
    }, []);

    /** Record a transaction confirmed on the success return page. */
    const recordTransaction = useCallback((txn) => {
        if (!txn?.id) return;
        setTransactions((prev) => {
            const next = mergeById(prev, [txn]);
            persistLocal(next);
            return next;
        });
    }, []);

    const value = { invoices, transactions, recordTransaction };

    return <PaymentContext.Provider value={value}>{children}</PaymentContext.Provider>;
};

export const usePayments = () => {
    const ctx = useContext(PaymentContext);
    if (!ctx) throw new Error('usePayments must be used within a <PaymentProvider>.');
    return ctx;
};
