package com.example.projectbnspumkm.data.repository

import com.example.projectbnspumkm.data.local.CartDao
import com.example.projectbnspumkm.data.local.CustomerDao
import com.example.projectbnspumkm.data.local.ProductDao
import com.example.projectbnspumkm.data.model.CartItem
import com.example.projectbnspumkm.data.model.Customer
import com.example.projectbnspumkm.data.model.Product
import com.example.projectbnspumkm.data.remote.ApiService
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow

class UmkmRepository(
    private val apiService: ApiService,
    private val productDao: ProductDao,
    private val customerDao: CustomerDao,
    private val cartDao: CartDao
) {
    // Products with Caching logic
    fun getProducts(): Flow<Resource<List<Product>>> = flow {
        emit(Resource.Loading())
        try {
            val remoteProducts = apiService.getProducts()
            productDao.insertProducts(remoteProducts)
        } catch (e: Exception) {
            emit(Resource.Error("Jaringan error, Tidak dapat menampilkan data", null))
        }
        
        productDao.getAllProducts().collect {
            emit(Resource.Success(it))
        }
    }

    fun getProductById(id: Int): Flow<Product?> = productDao.getProductById(id)

    suspend fun insertProducts(products: List<Product>) {
        productDao.insertProducts(products)
    }

    suspend fun updateProduct(product: Product): Resource<Product> {
        return try {
            productDao.updateProduct(product)
            Resource.Success(product)
        } catch (e: Exception) {
            Resource.Error("Gagal memperbarui produk, menampilkan data lokal", null)
        }
    }

    suspend fun insertCustomers(customers: List<Customer>) {
        customerDao.insertCustomers(customers)
    }
    fun getCustomers(): Flow<Resource<List<Customer>>> = flow {
        emit(Resource.Loading())
        try {
            val remoteCustomers = apiService.getCustomers()
            customerDao.insertCustomers(remoteCustomers)
        } catch (e: Exception) {
            emit(Resource.Error("Gagal mengambil data baru: ${e.message}"))
        }
        
        customerDao.getAllCustomers().collect {
            emit(Resource.Success(it))
        }
    }

    suspend fun addCustomer(customer: Customer): Resource<Customer> {
        return try {
            val result = apiService.addCustomer(customer)
            customerDao.insertCustomer(result)
            Resource.Success(result)
        } catch (e: Exception) {
            customerDao.insertCustomer(customer)
            Resource.Error("Gagal menambahkan customer: ${e.message}")
        }
    }

    suspend fun updateCustomers(customer: Customer): Resource<Customer> {
        return try {
            customerDao.updateCustomer(customer)
            Resource.Success(customer)
        } catch (e: Exception) {
            Resource.Error("Gagal memperbarui customer, menampilkan data lokal", null)
        }
    }

    suspend fun addProduct(product: Product): Resource<Product> {
        return try {
            val result = apiService.addProduct(product)
            productDao.insertProduct(result)
            Resource.Success(result)
        } catch (e: Exception) {
            productDao.insertProduct(product)
            Resource.Error("Gagal menambahkan produk: ${e.message}")
        }
    }

    fun getCartItems() = cartDao.getCartItems()
    suspend fun addToCart(item: CartItem) = cartDao.insertCartItem(item)
    suspend fun removeFromCart(item: CartItem) = cartDao.deleteCartItem(item)
    suspend fun clearCart() = cartDao.clearCart()
    suspend fun removeCustomer(customer: Customer) = customerDao.deleteCustomer(customer)
    suspend fun removeProduct(product: Product) = productDao.deleteProduct(product)
}

sealed class Resource<T>(
    val data: T? = null,
    val message: String? = null
) {
    class Success<T>(data: T) : Resource<T>(data)
    class Loading<T>(data: T? = null) : Resource<T>(data)
    class Error<T>(message: String, data: T? = null) : Resource<T>(data, message)
}
