package com.example.petstoremobile.fragments.listfragments.detailfragments;

import android.os.Bundle;
import android.util.Log;
import android.view.*;
import android.widget.*;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment;
import com.example.petstoremobile.R;
import com.example.petstoremobile.databinding.FragmentRefundBinding;
import com.example.petstoremobile.dtos.SaleDTO;
import com.example.petstoremobile.viewmodels.RefundViewModel;
import com.example.petstoremobile.utils.DialogUtils;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.DateTimeUtils;
import com.example.petstoremobile.utils.SpinnerUtils;
import dagger.hilt.android.AndroidEntryPoint;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

@AndroidEntryPoint
public class RefundFragment extends Fragment {

    private FragmentRefundBinding binding;
    private RefundViewModel viewModel;

    private final String[] PAYMENT_METHODS = {"Cash", "Card"};

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        binding = FragmentRefundBinding.inflate(inflater, container, false);
        viewModel = new ViewModelProvider(this).get(RefundViewModel.class);
        
        setupSpinner();
        observeViewModel();
        loadAllSales();

        Bundle args = getArguments();
        if (args != null && args.containsKey("saleId")) {
            binding.etRefundSaleId.setText(String.valueOf(args.getLong("saleId")));
        }

        binding.btnLoadSale.setOnClickListener(v -> loadSale());
        binding.btnProcessRefund.setOnClickListener(v -> processRefund());
        binding.btnRefundBack.setOnClickListener(v -> navigateBack());

        return binding.getRoot();
    }

    private void setupSpinner() {
        SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerRefundPayment, PAYMENT_METHODS);
    }

    private void observeViewModel() {
        viewModel.getAvailableItems().observe(getViewLifecycleOwner(), items -> renderOriginalItems());
        viewModel.getRefundCart().observe(getViewLifecycleOwner(), cart -> {
            renderRefundCart();
            updateRefundTotal();
            renderOriginalItems(); // Re-render to reflect quantities in cart
        });
    }

    private void setLoading(boolean loading) {
        if (binding != null && binding.progressBar != null) {
            binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
        }
    }

    private void loadAllSales() {
        viewModel.loadAllSales().observe(getViewLifecycleOwner(), resource -> {
            if (resource == null) return;
            setLoading(resource.status == Resource.Status.LOADING);
            if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
                viewModel.setAllSales(resource.data.getContent());
                Bundle args = getArguments();
                if (args != null && args.containsKey("saleId")) {
                    loadSale();
                }
            }
        });
    }

    private void loadSale() {
        String idStr = binding.etRefundSaleId.getText().toString().trim();
        if (idStr.isEmpty()) {
            Toast.makeText(getContext(), "Enter a Sale ID", Toast.LENGTH_SHORT).show();
            return;
        }

        long saleId;
        try { saleId = Long.parseLong(idStr); }
        catch (Exception e) {
            Toast.makeText(getContext(), "Invalid Sale ID", Toast.LENGTH_SHORT).show();
            return;
        }

        SaleDTO found = null;
        if (viewModel.getAllSalesList() != null) {
            for (SaleDTO s : viewModel.getAllSalesList()) {
                if (s.getSaleId() != null && s.getSaleId() == saleId) {
                    found = s; break;
                }
            }
        }

        if (found == null) {
            Toast.makeText(getContext(), "Sale #" + saleId + " not found", Toast.LENGTH_SHORT).show();
            return;
        }

        if (Boolean.TRUE.equals(found.getIsRefund())) {
            Toast.makeText(getContext(), "Select an original sale, not a refund record",
                    Toast.LENGTH_LONG).show();
            return;
        }

        viewModel.setCurrentSale(found);
        SaleDTO currentSale = viewModel.getCurrentSale();

        binding.tvSaleInfo.setVisibility(View.VISIBLE);
        binding.tvSaleInfo.setText("Sale #" + currentSale.getSaleId()
                + " | " + (currentSale.getSaleDate() != null
                ? DateTimeUtils.extractDate(currentSale.getSaleDate()) : "")
                + " | Employee: " + (currentSale.getEmployeeName() != null
                ? currentSale.getEmployeeName() : "")
                + " | Total: $" + currentSale.getTotalAmount()
                + " | Payment: " + currentSale.getPaymentMethod());

        if (currentSale.getPaymentMethod() != null) {
            SpinnerUtils.setSelectionByValue(binding.spinnerRefundPayment, currentSale.getPaymentMethod());
        }

        if (viewModel.getAvailableItems().getValue() == null || viewModel.getAvailableItems().getValue().isEmpty()) {
            Toast.makeText(getContext(), "This sale has no remaining refundable items", Toast.LENGTH_LONG).show();
            return;
        }

        binding.cardOriginalItems.setVisibility(View.VISIBLE);
        binding.cardRefundItems.setVisibility(View.VISIBLE);
        binding.cardPayment.setVisibility(View.VISIBLE);
        binding.btnProcessRefund.setVisibility(View.VISIBLE);
    }

    private void renderOriginalItems() {
        binding.llOriginalItems.removeAllViews();
        List<RefundViewModel.RefundItem> available = viewModel.getAvailableItems().getValue();
        if (available == null) return;

        addTableHeader(binding.llOriginalItems);

        for (RefundViewModel.RefundItem item : available) {
            int inCart = 0;
            if (viewModel.getRefundCart().getValue() != null) {
                for (RefundViewModel.RefundItem r : viewModel.getRefundCart().getValue()) {
                    if (r.prodId == item.prodId) { inCart = r.quantity; break; }
                }
            }
            int displayQty = item.quantity - inCart;
            if (displayQty <= 0) continue;

            LinearLayout row = buildItemRow(
                    item.productName,
                    displayQty,
                    item.unitPrice,
                    true,
                    () -> showQuantityDialog(item, displayQty)
            );
            binding.llOriginalItems.addView(row);
        }
    }

    private void renderRefundCart() {
        binding.llRefundItems.removeAllViews();
        List<RefundViewModel.RefundItem> cart = viewModel.getRefundCart().getValue();

        if (cart == null || cart.isEmpty()) {
            TextView empty = new TextView(getContext());
            empty.setText("No items added to refund yet");
            empty.setTextColor(0xFF888780);
            empty.setTextSize(13f);
            binding.llRefundItems.addView(empty);
            return;
        }

        addTableHeader(binding.llRefundItems);

        for (RefundViewModel.RefundItem item : cart) {
            LinearLayout row = buildItemRow(
                    item.productName,
                    item.quantity,
                    item.unitPrice,
                    false,
                    () -> viewModel.removeFromCart(item)
            );
            binding.llRefundItems.addView(row);
        }
    }

    private void addTableHeader(LinearLayout parent) {
        if (getContext() == null) return;
        LinearLayout header = new LinearLayout(getContext());
        header.setOrientation(LinearLayout.HORIZONTAL);
        header.setPadding(0, 0, 0, 8);

        String[] cols = {"Product", "Qty", "Unit Price", ""};
        float[] weights = {2f, 1f, 1f, 0.8f};
        for (int i = 0; i < cols.length; i++) {
            TextView tv = new TextView(getContext());
            tv.setLayoutParams(new LinearLayout.LayoutParams(0,
                    LinearLayout.LayoutParams.WRAP_CONTENT, weights[i]));
            tv.setText(cols[i]);
            tv.setTextColor(0xFF888780);
            tv.setTextSize(11f);
            header.addView(tv);
        }
        parent.addView(header);
    }

    private LinearLayout buildItemRow(String name, int qty, BigDecimal unitPrice,
                                      boolean isAdd, Runnable action) {
        if (getContext() == null) return new LinearLayout(getContext());
        LinearLayout row = new LinearLayout(getContext());
        row.setOrientation(LinearLayout.HORIZONTAL);
        row.setGravity(android.view.Gravity.CENTER_VERTICAL);
        row.setPadding(0, 8, 0, 8);

        TextView tvName = new TextView(getContext());
        tvName.setLayoutParams(new LinearLayout.LayoutParams(0,
                LinearLayout.LayoutParams.WRAP_CONTENT, 2f));
        tvName.setText(name);
        tvName.setTextSize(13f);
        tvName.setTextColor(0xFF3d3d3a);

        TextView tvQty = new TextView(getContext());
        tvQty.setLayoutParams(new LinearLayout.LayoutParams(0,
                LinearLayout.LayoutParams.WRAP_CONTENT, 1f));
        tvQty.setText(String.valueOf(qty));
        tvQty.setTextSize(13f);
        tvQty.setTextColor(0xFF3d3d3a);

        TextView tvPrice = new TextView(getContext());
        tvPrice.setLayoutParams(new LinearLayout.LayoutParams(0,
                LinearLayout.LayoutParams.WRAP_CONTENT, 1f));
        tvPrice.setText(unitPrice != null ? "$" + unitPrice : "");
        tvPrice.setTextSize(13f);
        tvPrice.setTextColor(0xFF3d3d3a);

        Button btn = new Button(getContext());
        LinearLayout.LayoutParams btnParams = new LinearLayout.LayoutParams(0,
                LinearLayout.LayoutParams.WRAP_CONTENT, 0.8f);
        btn.setLayoutParams(btnParams);
        btn.setText(isAdd ? "Add" : "Remove");
        btn.setTextSize(11f);
        btn.setBackgroundColor(isAdd ? 0xFF1a759f : 0xFFE24B4A);
        btn.setTextColor(0xFFFFFFFF);
        btn.setPadding(4, 4, 4, 4);
        btn.setOnClickListener(v -> action.run());

        row.addView(tvName);
        row.addView(tvQty);
        row.addView(tvPrice);
        row.addView(btn);
        return row;
    }

    private void showQuantityDialog(RefundViewModel.RefundItem item, int available) {
        EditText input = new EditText(getContext());
        input.setInputType(android.text.InputType.TYPE_CLASS_NUMBER);
        input.setText(String.valueOf(available));
        input.setSelectAllOnFocus(true);
        input.setPadding(40, 40, 40, 40);

        new androidx.appcompat.app.AlertDialog.Builder(requireContext())
                .setTitle("Refund Quantity")
                .setMessage("Product: " + item.productName + "\nAvailable: " + available)
                .setView(input)
                .setPositiveButton("Add to Refund", (d, w) -> {
                    String val = input.getText().toString().trim();
                    if (val.isEmpty()) return;
                    int qty;
                    try { qty = Integer.parseInt(val); }
                    catch (Exception e) {
                        Toast.makeText(getContext(), "Invalid quantity", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    if (qty <= 0) {
                        Toast.makeText(getContext(), "Quantity must be at least 1", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    if (qty > available) {
                        Toast.makeText(getContext(), "Cannot exceed " + available, Toast.LENGTH_SHORT).show();
                        return;
                    }
                    viewModel.addToCart(item, qty);
                })
                .setNegativeButton("Cancel", null)
                .show();
    }

    private void updateRefundTotal() {
        BigDecimal total = viewModel.calculateRefundTotal();
        binding.tvRefundTotal.setText("Refund Total: $" + total.setScale(2, RoundingMode.HALF_UP));
    }

    private void processRefund() {
        if (viewModel.getCurrentSale() == null) {
            Toast.makeText(getContext(), "Load a sale first", Toast.LENGTH_SHORT).show();
            return;
        }
        if (viewModel.getRefundCart().getValue() == null || viewModel.getRefundCart().getValue().isEmpty()) {
            Toast.makeText(getContext(), "Add at least one item to refund", Toast.LENGTH_SHORT).show();
            return;
        }

        String payment = PAYMENT_METHODS[binding.spinnerRefundPayment.getSelectedItemPosition()];
        final BigDecimal finalTotal = viewModel.calculateRefundTotal();

        DialogUtils.showConfirmDialog(requireContext(), "Confirm Refund", 
                "Process refund for Sale #" + viewModel.getCurrentSale().getSaleId()
                        + "?\nRefund amount: $" + finalTotal.setScale(2, RoundingMode.HALF_UP),
                () -> submitRefund(payment));
    }

    private void submitRefund(String payment) {
        viewModel.submitRefund(payment).observe(getViewLifecycleOwner(), resource -> {
            if (resource != null) {
                setLoading(resource.status == Resource.Status.LOADING);
                if (resource.status == Resource.Status.SUCCESS) {
                    Toast.makeText(getContext(), "Refund processed successfully!", Toast.LENGTH_LONG).show();
                    navigateBack();
                } else if (resource.status == Resource.Status.ERROR) {
                    Toast.makeText(getContext(), "Error: " + resource.message, Toast.LENGTH_LONG).show();
                }
            }
        });
    }

    private void navigateBack() {
        NavHostFragment.findNavController(this).popBackStack();
    }

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