import React, { useCallback, useEffect, useMemo, useState } from 'react' import { ActivityIndicator, FlatList, StyleSheet, Text, View } from 'react-native' import firebase from '../../config/firebase' import { background } from '../../assets' import Page from '../../layouts/Page' import { useUser } from '../../providers/UserDataProvider' import { gutters, Palette } from '../../styles' import { FONT_FAMILY } from '../../styles/Fonts' import CreditAmount from '../../components/CreditAmount' const ORDER_TYPE_LABELS = { GIFT: 'Crédit offert', COINS: 'Achat de coins', SONG: 'Génération de musique', SUBSCRIPTION: 'Abonnement', } const formatDateParts = (date) => { if (!date) { return { dateLabel: 'En attente de confirmation', timeLabel: '', } } try { const dateLabel = date.toLocaleDateString('fr-FR', { day: '2-digit', month: 'short', year: 'numeric', }) const timeLabel = date.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit', }) return { dateLabel, timeLabel } } catch (_error) { return { dateLabel: date.toString(), timeLabel: '', } } } const mapOrderType = (type) => ORDER_TYPE_LABELS[type] || 'Opération' const shortenIdentifier = (value, visible = 6) => { if (typeof value !== 'string') return null if (value.length <= visible + 2) return value return `${value.slice(0, visible)}…` } const OrderHistory = () => { const { currentUID } = useUser() || {} const [orders, setOrders] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) useEffect(() => { if (!currentUID) { setOrders([]) setLoading(false) return } setLoading(true) setError(null) const unsubscribe = firebase .firestore() .collection('orders') .where('userId', '==', currentUID) .orderBy('createdAt', 'desc') .onSnapshot( (snapshot) => { const nextOrders = snapshot.docs.map((doc) => { const rawData = doc.data() || {} const createdAt = typeof rawData.createdAt?.toDate === 'function' ? rawData.createdAt.toDate() : null return { id: doc.id, ...rawData, createdAt, } }) setOrders(nextOrders) setLoading(false) }, (firestoreError) => { console.warn( '[OrderHistory] Unable to load orders', firestoreError?.message || firestoreError ) setError(firestoreError?.message || "Impossible de récupérer l'historique des commandes.") setLoading(false) } ) return () => { if (typeof unsubscribe === 'function') { unsubscribe() } } }, [currentUID]) const renderOrder = useCallback(({ item }) => { const amountValue = typeof item.amount === 'number' && Number.isFinite(item.amount) ? item.amount : 0 const isPositive = amountValue > 0 const amountTextStyle = [ styles.orderAmount, isPositive ? styles.amountPositive : styles.amountNegative, ] const { dateLabel } = formatDateParts(item.createdAt) let reasonLabel = mapOrderType(item.type) if (item.type === 'GIFT') { const reason = item.metadata?.reason if (reason === 'WELCOME_BONUS') { reasonLabel = 'Crédit de bienvenue' } else if (typeof reason === 'string' && reason.trim()) { reasonLabel = reason.trim() } } else if (item.type === 'SONG') { reasonLabel = 'Génération de musique' } else if (item.type === 'COINS') { if (item.metadata?.coinPackKey) { const shortenedPack = shortenIdentifier(item.metadata.coinPackKey, 10) reasonLabel = `Pack ${shortenedPack || item.metadata.coinPackKey}` } else if (typeof item.metadata?.source === 'string' && item.metadata.source.trim()) { const source = item.metadata.source.trim() reasonLabel = source === 'STRIPE_CHECKOUT' ? 'Recharge Stripe' : source } else { reasonLabel = 'Rechargement de coins' } } else if (item.type === 'SUBSCRIPTION') { const rawPeriod = typeof item.metadata?.billingPeriod === 'string' ? item.metadata.billingPeriod.toLowerCase() : null reasonLabel = rawPeriod === 'annual' ? 'Abonnement annuel' : rawPeriod === 'monthly' ? 'Abonnement mensuel' : 'Abonnement' } return ( {reasonLabel} {dateLabel} ) }, []) const keyExtractor = useCallback((item) => item.id, []) const listEmptyComponent = useMemo(() => { if (loading) { return null } if (!currentUID) { return ( Connecte-toi pour consulter l'historique de tes commandes. ) } if (error) { return {error} } return Aucune opération de coins pour le moment. }, [loading, currentUID, error]) return ( {loading ? ( ) : ( } ListEmptyComponent={listEmptyComponent} /> )} ) } const styles = StyleSheet.create({ container: { flex: 1, paddingHorizontal: gutters, paddingTop: gutters, }, loaderContainer: { flex: 1, alignItems: 'center', justifyContent: 'center', }, listContent: { paddingBottom: gutters * 2, }, emptyListContent: { flexGrow: 1, justifyContent: 'center', }, orderCard: { padding: 16, borderRadius: 16, backgroundColor: Palette.ultraLightWhite, borderWidth: 1, borderColor: 'rgba(255, 255, 255, 0.08)', gap: 6, }, orderAmount: { fontSize: 16, fontFamily: FONT_FAMILY.InterSemiBold, }, amountPositive: { color: Palette.green, }, amountNegative: { color: Palette.red, }, orderReason: { fontSize: 14, fontFamily: FONT_FAMILY.InterRegular, color: Palette.white, }, orderTimestamp: { fontSize: 12, color: Palette.grayMid, fontFamily: FONT_FAMILY.InterMedium, }, emptyText: { textAlign: 'center', color: Palette.grayMid, fontSize: 15, fontFamily: FONT_FAMILY.InterRegular, }, errorText: { textAlign: 'center', color: Palette.red, fontSize: 15, fontFamily: FONT_FAMILY.InterRegular, }, }) export default OrderHistory