package com.example.petstoremobile.viewmodels;

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

import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.dtos.SaleDTO;
import com.example.petstoremobile.repositories.SaleRepository;
import com.example.petstoremobile.utils.Resource;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;

import dagger.hilt.android.lifecycle.HiltViewModel;

@HiltViewModel
public class RefundViewModel extends ViewModel {
    private final SaleRepository saleRepository;

    private final MutableLiveData<List<SaleDTO>> allSales = new MutableLiveData<>(new ArrayList<>());
    private final MutableLiveData<SaleDTO> currentSale = new MutableLiveData<>();
    private final MutableLiveData<List<RefundItem>> availableItems = new MutableLiveData<>(new ArrayList<>());
    private final MutableLiveData<List<RefundItem>> refundCart = new MutableLiveData<>(new ArrayList<>());

    @Inject
    public RefundViewModel(SaleRepository saleRepository) {
        this.saleRepository = saleRepository;
    }

    public LiveData<Resource<PageResponse<SaleDTO>>> loadAllSales() {
        return saleRepository.getAllSales(0, 1000, null, null, null, null, null, "saleDate,desc");
    }

    public void setAllSales(List<SaleDTO> sales) {
        allSales.setValue(sales);
    }

    public List<SaleDTO> getAllSalesList() {
        return allSales.getValue();
    }

    public void setCurrentSale(SaleDTO sale) {
        currentSale.setValue(sale);
        buildRefundableItems();
    }

    public SaleDTO getCurrentSale() {
        return currentSale.getValue();
    }

    public LiveData<List<RefundItem>> getAvailableItems() {
        return availableItems;
    }

    public LiveData<List<RefundItem>> getRefundCart() {
        return refundCart;
    }

    private void buildRefundableItems() {
        SaleDTO sale = currentSale.getValue();
        List<SaleDTO> sales = allSales.getValue();
        if (sale == null || sales == null || sale.getItems() == null) {
            availableItems.setValue(new ArrayList<>());
            return;
        }

        Map<Long, Integer> alreadyRefunded = new HashMap<>();
        for (SaleDTO s : sales) {
            if (Boolean.TRUE.equals(s.getIsRefund())
                    && sale.getSaleId().equals(s.getOriginalSaleId())
                    && s.getItems() != null) {
                for (SaleDTO.SaleItemDTO item : s.getItems()) {
                    if (item.getProdId() != null && item.getQuantity() != null) {
                        alreadyRefunded.merge(item.getProdId(),
                                Math.abs(item.getQuantity()), Integer::sum);
                    }
                }
            }
        }

        List<RefundItem> items = new ArrayList<>();
        for (SaleDTO.SaleItemDTO item : sale.getItems()) {
            if (item.getProdId() == null || item.getQuantity() == null) continue;
            int refunded = alreadyRefunded.getOrDefault(item.getProdId(), 0);
            int remaining = item.getQuantity() - refunded;
            if (remaining > 0) {
                items.add(new RefundItem(
                        item.getProdId(),
                        item.getProductName() != null ? item.getProductName() : "Unknown",
                        remaining,
                        item.getUnitPrice()
                ));
            }
        }
        availableItems.setValue(items);
        refundCart.setValue(new ArrayList<>());
    }

    public void addToCart(RefundItem item, int qty) {
        List<RefundItem> cart = new ArrayList<>(refundCart.getValue());
        boolean merged = false;
        for (int i = 0; i < cart.size(); i++) {
            if (cart.get(i).prodId == item.prodId) {
                RefundItem existing = cart.get(i);
                cart.set(i, new RefundItem(existing.prodId, existing.productName, existing.quantity + qty, existing.unitPrice));
                merged = true;
                break;
            }
        }
        if (!merged) {
            cart.add(new RefundItem(item.prodId, item.productName, qty, item.unitPrice));
        }
        refundCart.setValue(cart);
    }

    public void removeFromCart(RefundItem item) {
        List<RefundItem> cart = new ArrayList<>(refundCart.getValue());
        cart.remove(item);
        refundCart.setValue(cart);
    }

    public BigDecimal calculateRefundTotal() {
        SaleDTO sale = currentSale.getValue();
        List<RefundItem> cart = refundCart.getValue();
        if (sale == null || cart == null || cart.isEmpty()) return BigDecimal.ZERO;

        BigDecimal cartSubtotal = BigDecimal.ZERO;
        for (RefundItem item : cart) cartSubtotal = cartSubtotal.add(item.getTotal());

        BigDecimal originalSubtotal = sale.getSubtotalAmount();
        if (originalSubtotal == null || originalSubtotal.compareTo(BigDecimal.ZERO) == 0) {
            if (sale.getItems() != null) {
                originalSubtotal = BigDecimal.ZERO;
                for (SaleDTO.SaleItemDTO item : sale.getItems()) {
                    if (item.getUnitPrice() != null && item.getQuantity() != null)
                        originalSubtotal = originalSubtotal.add(item.getUnitPrice().multiply(BigDecimal.valueOf(Math.abs(item.getQuantity()))));
                }
            }
        }
        if (originalSubtotal == null || originalSubtotal.compareTo(BigDecimal.ZERO) == 0) return cartSubtotal;

        BigDecimal originalTotal = sale.getTotalAmount();
        if (originalTotal == null) return cartSubtotal;

        BigDecimal ratio = cartSubtotal.divide(originalSubtotal, 10, RoundingMode.HALF_UP);
        return originalTotal.abs().multiply(ratio).setScale(2, RoundingMode.HALF_UP);
    }

    public LiveData<Resource<SaleDTO>> submitRefund(String paymentMethod) {
        SaleDTO sale = currentSale.getValue();
        List<RefundItem> cart = refundCart.getValue();
        if (sale == null || cart == null || cart.isEmpty()) return null;

        List<SaleDTO.SaleItemDTO> items = new ArrayList<>();
        for (RefundItem item : cart) {
            items.add(new SaleDTO.SaleItemDTO(item.prodId, -item.quantity));
        }

        SaleDTO dto = new SaleDTO(
                sale.getStoreId(),
                paymentMethod,
                items,
                true,
                sale.getSaleId(),
                null
        );

        return saleRepository.createSale(dto);
    }

    public static class RefundItem {
        public long prodId;
        public String productName;
        public int quantity;
        public BigDecimal unitPrice;

        public RefundItem(long prodId, String productName, int quantity, BigDecimal unitPrice) {
            this.prodId = prodId;
            this.productName = productName;
            this.quantity = quantity;
            this.unitPrice = unitPrice;
        }

        public BigDecimal getTotal() {
            return unitPrice != null ? unitPrice.multiply(BigDecimal.valueOf(quantity)) : BigDecimal.ZERO;
        }
    }
}
