package com.example.petstoremobile.fragments.listfragments;

import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.example.petstoremobile.R;
import com.example.petstoremobile.adapters.SaleAdapter;
import com.example.petstoremobile.api.auth.TokenManager;
import com.example.petstoremobile.databinding.FragmentSaleBinding;
import com.example.petstoremobile.dtos.CustomerDTO;
import com.example.petstoremobile.dtos.SaleDTO;
import com.example.petstoremobile.dtos.StoreDTO;
import com.example.petstoremobile.utils.SpinnerUtils;
import com.example.petstoremobile.utils.UIUtils;
import com.example.petstoremobile.viewmodels.SaleListViewModel;

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

import javax.inject.Inject;

import dagger.hilt.android.AndroidEntryPoint;

@AndroidEntryPoint
public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickListener {

    private FragmentSaleBinding binding;
    private final List<SaleDTO> saleList = new ArrayList<>();
    private SaleAdapter adapter;
    private SaleListViewModel viewModel;

    @Inject TokenManager tokenManager;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        binding = FragmentSaleBinding.inflate(inflater, container, false);
        return binding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        viewModel = new ViewModelProvider(this).get(SaleListViewModel.class);

        setupRecyclerView();
        setupSearch();
        setupStoreFilter();
        setupPaymentMethodFilter();
        setupRefundStatusFilter();
        setupCustomerFilter();
        setupSwipeRefresh();
        setupFilterToggle();
        observeViewModel();

        loadSales(true);

        UIUtils.setupHamburgerMenu(binding.btnHamburger, this);

        if (isAdmin()) {
            binding.fabAddSale.setVisibility(View.GONE);
            binding.btnOpenRefund.setVisibility(View.GONE);
        }

        binding.fabAddSale.setOnClickListener(v ->
                NavHostFragment.findNavController(this).navigate(R.id.nav_sale_detail));

        binding.btnOpenRefund.setOnClickListener(v ->
                NavHostFragment.findNavController(this).navigate(R.id.nav_refund));
    }

    private void observeViewModel() {
        viewModel.getSales().observe(getViewLifecycleOwner(), list -> {
            saleList.clear();
            saleList.addAll(list);
            adapter.notifyDataSetChanged();
        });

        viewModel.getStores().observe(getViewLifecycleOwner(), list -> {
            SpinnerUtils.populateWhiteSpinner(requireContext(), binding.spinnerStore, list,
                    StoreDTO::getStoreName, "All Stores", null, StoreDTO::getStoreId);
        });

        viewModel.getCustomers().observe(getViewLifecycleOwner(), list -> {
            SpinnerUtils.populateWhiteSpinner(requireContext(), binding.spinnerCustomer, list,
                    CustomerDTO::getFullName, "All Customers", null, CustomerDTO::getCustomerId);
        });

        viewModel.getIsLoading().observe(getViewLifecycleOwner(), loading -> {
            binding.swipeRefreshSale.setRefreshing(loading);
        });
    }

    @Override
    public void onResume() {
        super.onResume();
        if (!isStaff()) viewModel.loadStores();
        viewModel.loadCustomers();
    }

    private void setupFilterToggle() {
        if (isStaff()) {
            UIUtils.setupFilterToggle(binding.btnToggleFilter, binding.layoutFilter, binding.etSearchSale,
                    binding.spinnerPaymentMethod, binding.spinnerRefundStatus, binding.spinnerCustomer);
            binding.spinnerStore.setVisibility(View.GONE);
        } else {
            UIUtils.setupFilterToggle(binding.btnToggleFilter, binding.layoutFilter, binding.etSearchSale,
                    binding.spinnerPaymentMethod, binding.spinnerStore, binding.spinnerRefundStatus, binding.spinnerCustomer);
        }
    }

    private boolean isStaff() {
        return "STAFF".equalsIgnoreCase(tokenManager.getRole());
    }

    private boolean isAdmin() {
        return "ADMIN".equalsIgnoreCase(tokenManager.getRole());
    }

    private void setupStoreFilter() {
        SpinnerUtils.setupFilterSpinner(binding.spinnerStore, () -> loadSales(true));
    }

    private void setupPaymentMethodFilter() {
        String[] paymentMethods = {"All Payments", "Cash", "Card"};
        SpinnerUtils.setupStringFilterSpinner(requireContext(), binding.spinnerPaymentMethod, paymentMethods, () -> loadSales(true));
    }

    private void setupRefundStatusFilter() {
        String[] refundStatuses = {"All Status", "Sale", "Refund"};
        SpinnerUtils.setupStringFilterSpinner(requireContext(), binding.spinnerRefundStatus, refundStatuses, () -> loadSales(true));
    }

    private void setupCustomerFilter() {
        SpinnerUtils.setupFilterSpinner(binding.spinnerCustomer, () -> loadSales(true));
    }

    private void setupRecyclerView() {
        adapter = new SaleAdapter(saleList, this);
        binding.recyclerViewSales.setLayoutManager(new LinearLayoutManager(getContext()));
        binding.recyclerViewSales.setAdapter(adapter);

        binding.recyclerViewSales.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                if (dy <= 0) return;
                LinearLayoutManager lm = (LinearLayoutManager) binding.recyclerViewSales.getLayoutManager();
                if (lm != null) {
                    int visible = lm.getChildCount();
                    int total = lm.getItemCount();
                    int firstVis = lm.findFirstVisibleItemPosition();
                    Boolean isLoading = viewModel.getIsLoading().getValue();
                    if ((isLoading == null || !isLoading) && !viewModel.isLastPage() && (visible + firstVis) >= total - 3) {
                        loadSales(false);
                    }
                }
            }
        });
    }

    private void setupSearch() {
        UIUtils.attachSearch(binding.etSearchSale, () -> loadSales(true));
    }

    private void setupSwipeRefresh() {
        binding.swipeRefreshSale.setOnRefreshListener(() -> loadSales(true));
    }

    private void loadSales(boolean reset) {
        String query = binding.etSearchSale != null ? binding.etSearchSale.getText().toString().trim() : "";
        if (query.isEmpty()) query = null;

        String paymentMethod = null;
        if (binding.spinnerPaymentMethod.getSelectedItemPosition() > 0) {
            paymentMethod = (String) binding.spinnerPaymentMethod.getSelectedItem();
        }

        Long storeId;
        if (isStaff()) {
            storeId = tokenManager.getPrimaryStoreId();
        } else {
            storeId = null;
            List<StoreDTO> stores = viewModel.getStores().getValue();
            if (binding.spinnerStore.getSelectedItemPosition() > 0 && stores != null && !stores.isEmpty()) {
                storeId = stores.get(binding.spinnerStore.getSelectedItemPosition() - 1).getStoreId();
            }
        }

        Boolean isRefund = null;
        if (binding.spinnerRefundStatus.getSelectedItemPosition() > 0) {
            isRefund = binding.spinnerRefundStatus.getSelectedItemPosition() == 2;
        }

        Long customerId = null;
        List<CustomerDTO> customerList = viewModel.getCustomers().getValue();
        if (binding.spinnerCustomer.getSelectedItemPosition() > 0 && customerList != null && !customerList.isEmpty()) {
            customerId = customerList.get(binding.spinnerCustomer.getSelectedItemPosition() - 1).getCustomerId();
        }

        viewModel.loadSales(reset, query, paymentMethod, storeId, isRefund, customerId);
    }

    @Override
    public void onSaleClick(int position) {
        if (position < 0 || position >= saleList.size()) return;
        SaleDTO sale = saleList.get(position);
        Bundle args = new Bundle();
        if (sale.getSaleId() != null) {
            args.putLong("saleId", sale.getSaleId());
            args.putBoolean("viewOnly", true);
        }
        if (sale.getIsRefund() != null) {
            args.putBoolean("isRefund", sale.getIsRefund());
        }
        NavHostFragment.findNavController(this).navigate(R.id.nav_sale_detail, args);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }
}
