package com.example.petstoremobile.fragments.listfragments;

import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

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 com.example.petstoremobile.R;
import com.example.petstoremobile.adapters.AdoptionAdapter;
import com.example.petstoremobile.api.auth.TokenManager;
import com.example.petstoremobile.databinding.FragmentAdoptionBinding;
import com.example.petstoremobile.dtos.AdoptionDTO;
import com.example.petstoremobile.dtos.StoreDTO;
import com.example.petstoremobile.utils.BulkDeleteHandler;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.SpinnerUtils;
import com.example.petstoremobile.utils.UIUtils;
import com.example.petstoremobile.viewmodels.AdoptionListViewModel;
import com.example.petstoremobile.utils.EventDecorator;
import com.prolificinteractive.materialcalendarview.CalendarDay;
import com.prolificinteractive.materialcalendarview.CalendarMode;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;

import javax.inject.Inject;

import dagger.hilt.android.AndroidEntryPoint;

@AndroidEntryPoint
public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdoptionClickListener {

    private FragmentAdoptionBinding binding;
    private List<AdoptionDTO> adoptionList = new ArrayList<>();
    private AdoptionAdapter adapter;
    private AdoptionListViewModel viewModel;
    private BulkDeleteHandler bulkDeleteHandler;
    private CalendarDay selectedCalendarDay;
    private boolean isMonthMode = false;
    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());

    @Inject TokenManager tokenManager;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        viewModel = new ViewModelProvider(this).get(AdoptionListViewModel.class);
    }

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

        setupRecyclerView();
        setupSearch();
        setupStatusFilter();
        setupStoreFilter();
        setupSwipeRefresh();
        setupCalendar();
        setupFilterToggle();
        setupBulkDelete();
        observeViewModel();

        binding.fabAddAdoption.setOnClickListener(v -> openDetail(-1));

        UIUtils.setupHamburgerMenu(binding.btnHamburgerAdoption, this);

        binding.btnToggleCalendarModeAdoption.setOnClickListener(v -> toggleCalendarMode());

        return binding.getRoot();
    }

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

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

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

    private void setupBulkDelete() {
        bulkDeleteHandler = new BulkDeleteHandler(
                this,
                binding.layoutBulkDelete,
                binding.tvSelectionCount,
                binding.btnBulkDelete,
                adapter,
                "adoption",
                viewModel::bulkDeleteAdoptions,
                () -> loadAdoptions(true)
        );
    }

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

    private void toggleCalendarMode() {
        isMonthMode = !isMonthMode;
        binding.calendarViewAdoption.state().edit()
                .setCalendarDisplayMode(isMonthMode ? CalendarMode.MONTHS : CalendarMode.WEEKS)
                .commit();
    }

    private void setupFilterToggle() {
        if (isStaff()) {
            UIUtils.setupFilterToggle(binding.btnToggleFilterAdoption, binding.layoutFilterAdoption,
                    binding.etSearchAdoption, binding.spinnerStatusAdoption);
            binding.spinnerStoreAdoption.setVisibility(View.GONE);
        } else {
            UIUtils.setupFilterToggle(binding.btnToggleFilterAdoption, binding.layoutFilterAdoption,
                    binding.etSearchAdoption, binding.spinnerStatusAdoption, binding.spinnerStoreAdoption);
        }
    }

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

    private void setupCalendar() {
        binding.calendarViewAdoption.setOnDateChangedListener((widget, date, selected) -> {
            if (selected) {
                if (date.equals(selectedCalendarDay)) {
                    selectedCalendarDay = null;
                    binding.calendarViewAdoption.clearSelection();
                } else {
                    selectedCalendarDay = date;
                }
            } else {
                selectedCalendarDay = null;
            }
            loadAdoptions(true);
        });
    }

    private void updateCalendarDecorators() {
        HashSet<CalendarDay> datesWithAdoptions = new HashSet<>();
        for (AdoptionDTO adoption : adoptionList) {
            try {
                if (adoption.getAdoptionDate() != null) {
                    Date date = dateFormat.parse(adoption.getAdoptionDate());
                    if (date != null) {
                        Calendar cal = Calendar.getInstance();
                        cal.setTime(date);
                        datesWithAdoptions.add(CalendarDay.from(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH)));
                    }
                }
            } catch (ParseException e) {
                Log.e("AdoptionFragment", "Error parsing date: " + adoption.getAdoptionDate());
            }
        }
        binding.calendarViewAdoption.removeDecorators();
        binding.calendarViewAdoption.addDecorator(new EventDecorator(Color.RED, datesWithAdoptions));
    }

    private void setupRecyclerView() {
        adapter = new AdoptionAdapter(adoptionList, this);
        binding.recyclerViewAdoptions.setLayoutManager(new LinearLayoutManager(getContext()));
        binding.recyclerViewAdoptions.setAdapter(adapter);

        binding.recyclerViewAdoptions.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                if (dy <= 0) return;
                LinearLayoutManager lm = (LinearLayoutManager) binding.recyclerViewAdoptions.getLayoutManager();
                if (lm == null) return;
                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) {
                    loadAdoptions(false);
                }
            }
        });
    }

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

    private void setupStatusFilter() {
        String[] statuses = {"All Statuses", "Completed", "Pending", "Missed", "Cancelled"};
        SpinnerUtils.setupStringFilterSpinner(requireContext(), binding.spinnerStatusAdoption, statuses, () -> loadAdoptions(true));
    }

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

    private void setupSwipeRefresh() {
        binding.swipeRefreshAdoption.setOnRefreshListener(() -> loadAdoptions(true));
    }

    private void loadAdoptions(boolean reset) {
        String query = binding.etSearchAdoption.getText().toString().trim();
        String status = binding.spinnerStatusAdoption.getSelectedItem() != null ? binding.spinnerStatusAdoption.getSelectedItem().toString() : "All Statuses";

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

        String selectedDateString = null;
        if (selectedCalendarDay != null) {
            selectedDateString = String.format(Locale.getDefault(), "%04d-%02d-%02d",
                    selectedCalendarDay.getYear(), selectedCalendarDay.getMonth(), selectedCalendarDay.getDay());
        }

        if (status.equals("All Statuses")) status = null;
        else status = status.toUpperCase();

        viewModel.loadAdoptions(reset, query, status, storeId, selectedDateString, null);
    }

    private void openDetail(int position) {
        Bundle args = new Bundle();
        if (position != -1) {
            AdoptionDTO a = adoptionList.get(position);
            args.putLong("adoptionId", a.getAdoptionId());
        }
        NavHostFragment.findNavController(this).navigate(R.id.nav_adoption_detail, args);
    }

    @Override
    public void onAdoptionClick(int position) { openDetail(position); }

    @Override
    public void onSelectionChanged(int selectedCount) {
        if (bulkDeleteHandler != null) {
            bulkDeleteHandler.onSelectionChanged(selectedCount);
        }
    }

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