package com.aistudio.bonjuteri.jwlry.data import android.content.Context import android.util.Log import com.aistudio.bonjuteri.jwlry.model.CartItem import com.aistudio.bonjuteri.jwlry.model.Product import com.google.firebase.Timestamp import com.google.firebase.auth.FirebaseAuth import com.google.firebase.firestore.FirebaseFirestore import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.tasks.await class CartRepository( private val firestore: FirebaseFirestore, private val auth: FirebaseAuth ) { companion object { private const val TAG = "CartRepository" const val FREE_SHIPPING_THRESHOLD = 500.0 const val STANDARD_SHIPPING_COST = 49.90 @Volatile private var INSTANCE: CartRepository? = null fun getInstance(context: Context): CartRepository { return INSTANCE ?: synchronized(this) { INSTANCE ?: CartRepository( FirestoreHelper.getFirestore(context), FirebaseAuth.getInstance() ).also { INSTANCE = it } } } } private fun requireUserId(): String { return auth.currentUser?.uid ?: throw IllegalStateException("Sepet işlemleri için oturum açmalısınız.") } fun observeCart(): Flow> = callbackFlow { val uid = auth.currentUser?.uid if (uid == null) { trySend(emptyList()) close() return@callbackFlow } val cartRef = firestore.collection("users").document(uid).collection("cart") val listener = cartRef.addSnapshotListener { snapshot, error -> if (error != null) { FirestoreHelper.handleFirestoreError(error, "observeCart", cartRef.path) trySend(emptyList()) return@addSnapshotListener } val items = snapshot?.documents?.mapNotNull { it.toObject(CartItem::class.java) } ?: emptyList() trySend(items) } awaitClose { listener.remove() } } suspend fun addToCart(product: Product, quantityToAdd: Long = 1L): Result { return try { val uid = requireUserId() // Verify real-time stock on Firestore before adding (with fallback if offline) val liveProduct = try { val doc = firestore.collection(ProductRepository.PRODUCTS_COLLECTION) .document(product.id) .get() .await() doc.toObject(Product::class.java) ?: product } catch (_: Exception) { product } if (liveProduct.stock <= 0L) { return Result.failure(IllegalStateException("Bu ürün tükenmiştir.")) } val cartItemRef = firestore.collection("users").document(uid) .collection("cart").document(product.id) val existingSnapshot = cartItemRef.get().await() val existingItem = existingSnapshot.toObject(CartItem::class.java) val currentQty = existingItem?.quantity ?: 0L val targetQty = currentQty + quantityToAdd if (targetQty > liveProduct.stock) { return Result.failure(IllegalStateException("Maksimum mevcut stok: ${liveProduct.stock} adet.")) } val item = CartItem( id = product.id, productId = product.id, title = liveProduct.title, imageUrl = liveProduct.imageUrl, price = liveProduct.price, quantity = targetQty, maxStock = liveProduct.stock, updatedAt = Timestamp.now() ) cartItemRef.set(item).await() Result.success(Unit) } catch (e: Throwable) { Log.e(TAG, "Sepete ekleme hatası: ${e.message}", e) Result.failure(Exception(e.localizedMessage ?: "Sepete eklenemedi.")) } } suspend fun updateQuantity(productId: String, newQuantity: Long): Result { return try { val uid = requireUserId() val cartItemRef = firestore.collection("users").document(uid) .collection("cart").document(productId) if (newQuantity <= 0L) { cartItemRef.delete().await() return Result.success(Unit) } // Verify live stock val productDoc = firestore.collection(ProductRepository.PRODUCTS_COLLECTION) .document(productId) .get() .await() val liveProduct = productDoc.toObject(Product::class.java) val maxStock = liveProduct?.stock ?: 99L if (newQuantity > maxStock) { return Result.failure(IllegalStateException("Stok sınırı: $maxStock adet.")) } cartItemRef.update( mapOf( "quantity" to newQuantity, "maxStock" to maxStock, "updatedAt" to Timestamp.now() ) ).await() Result.success(Unit) } catch (e: Throwable) { Result.failure(Exception(e.localizedMessage ?: "Adet güncellenemedi.")) } } suspend fun removeFromCart(productId: String): Result { return try { val uid = requireUserId() firestore.collection("users").document(uid) .collection("cart").document(productId) .delete() .await() Result.success(Unit) } catch (e: Throwable) { Result.failure(Exception(e.localizedMessage ?: "Sepetten çıkarılamadı.")) } } suspend fun clearCart(): Result { return try { val uid = requireUserId() val cartRef = firestore.collection("users").document(uid).collection("cart") val snapshots = cartRef.get().await() val batch = firestore.batch() for (doc in snapshots.documents) { batch.delete(doc.reference) } batch.commit().await() Result.success(Unit) } catch (e: Throwable) { Result.failure(Exception(e.localizedMessage ?: "Sepet temizlenemedi.")) } } }