package com.example.petstoremobile.viewmodels;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

import com.example.petstoremobile.dtos.BulkDeleteRequest;
import com.example.petstoremobile.dtos.ProductDTO;
import com.example.petstoremobile.dtos.ProductSupplierDTO;
import com.example.petstoremobile.dtos.SupplierDTO;
import com.example.petstoremobile.repositories.ProductRepository;
import com.example.petstoremobile.repositories.ProductSupplierRepository;
import com.example.petstoremobile.repositories.SupplierRepository;
import com.example.petstoremobile.utils.Resource;

import androidx.lifecycle.Observer;

import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;

import dagger.hilt.android.lifecycle.HiltViewModel;

@HiltViewModel
public class ProductSupplierListViewModel extends ViewModel {
    private final ProductSupplierRepository psRepository;
    private final ProductRepository productRepository;
    private final SupplierRepository supplierRepository;

    private final MutableLiveData<List<ProductSupplierDTO>> productSuppliers = new MutableLiveData<>(new ArrayList<>());
    private final MutableLiveData<List<ProductDTO>> products = new MutableLiveData<>(new ArrayList<>());
    private final MutableLiveData<List<SupplierDTO>> suppliers = new MutableLiveData<>(new ArrayList<>());
    private final MutableLiveData<Boolean> isLoading = new MutableLiveData<>(false);

    private int currentPage = 0;
    private boolean isLastPage = false;
    private static final int PAGE_SIZE = 20;

    @Inject
    public ProductSupplierListViewModel(ProductSupplierRepository psRepository, ProductRepository productRepository, SupplierRepository supplierRepository) {
        this.psRepository = psRepository;
        this.productRepository = productRepository;
        this.supplierRepository = supplierRepository;
    }

    public LiveData<List<ProductSupplierDTO>> getProductSuppliers() { return productSuppliers; }
    public LiveData<List<ProductDTO>> getProducts() { return products; }
    public LiveData<List<SupplierDTO>> getSuppliers() { return suppliers; }
    public LiveData<Boolean> getIsLoading() { return isLoading; }
    public boolean isLastPage() { return isLastPage; }

    public void loadProductSuppliers(boolean reset, String query, Long productId, Long supplierId) {
        if (isLoading.getValue() != null && isLoading.getValue() && !reset) return;

        if (reset) {
            currentPage = 0;
            isLastPage = false;
        }

        if (isLastPage) return;

        isLoading.setValue(true);
        observeOnce(psRepository.getAllProductSuppliers(currentPage, PAGE_SIZE, query, productId, supplierId, "productName"), resource -> {
            if (resource != null) {
                if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
                    List<ProductSupplierDTO> currentList = reset ? new ArrayList<>() : new ArrayList<>(productSuppliers.getValue());
                    currentList.addAll(resource.data.getContent());
                    productSuppliers.setValue(currentList);
                    isLastPage = resource.data.isLast();
                    if (!isLastPage) currentPage++;
                    isLoading.setValue(false);
                } else if (resource.status == Resource.Status.ERROR) {
                    isLoading.setValue(false);
                }
            }
        });
    }

    public void loadFilterData() {
        observeOnce(productRepository.getAllProducts(null, null, 0, 100, "prodName"), resource -> {
            if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
                products.setValue(resource.data.getContent());
            }
        });

        observeOnce(supplierRepository.getAllSuppliers(0, 100, null, "supCompany"), resource -> {
            if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
                suppliers.setValue(resource.data.getContent());
            }
        });
    }

    private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
        liveData.observeForever(new Observer<Resource<T>>() {
            @Override
            public void onChanged(Resource<T> resource) {
                if (resource == null || resource.status != Resource.Status.LOADING) {
                    liveData.removeObserver(this);
                }
                handler.onChanged(resource);
            }
        });
    }

    public LiveData<Resource<Void>> bulkDeleteProductSuppliers(List<String> ids) {
        return psRepository.bulkDeleteProductSuppliers(new BulkDeleteRequest(ids));
    }
}
