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

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 android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.example.petstoremobile.R;
import com.example.petstoremobile.api.auth.TokenManager;
import com.example.petstoremobile.databinding.FragmentPetDetailBinding;
import com.example.petstoremobile.dtos.DropdownDTO;
import com.example.petstoremobile.dtos.PetDTO;
import com.example.petstoremobile.utils.ActivityLogger;
import com.example.petstoremobile.utils.DateTimeUtils;
import com.example.petstoremobile.utils.DialogUtils;
import com.example.petstoremobile.utils.InputValidator;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.SpinnerUtils;
import com.example.petstoremobile.utils.UIUtils;
import com.example.petstoremobile.viewmodels.PetDetailViewModel;

import java.util.List;
import java.util.Locale;

import javax.inject.Inject;

import dagger.hilt.android.AndroidEntryPoint;

/**
 * Fragment for displaying and editing pet details.
 */
@AndroidEntryPoint
public class PetDetailFragment extends Fragment {

    private FragmentPetDetailBinding binding;
    private PetDetailViewModel viewModel;
    private boolean isUpdatingUI = false;

    @Inject TokenManager tokenManager;

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

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

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        setupSpinner();
        observeViewModel();
        handleArguments();
        viewModel.loadInitialFormData();

        binding.btnBack.setOnClickListener(v -> navigateBack());
        binding.btnSavePet.setOnClickListener(v -> savePet());
        binding.btnDeletePet.setOnClickListener(v -> deletePet());
    }

    private void observeViewModel() {
        viewModel.getViewState().observe(getViewLifecycleOwner(), this::applyViewState);

        viewModel.getCustomerList().observe(getViewLifecycleOwner(), list -> {
            PetDetailViewModel.ViewState state = viewModel.getViewState().getValue();
            Long selectedCustomerId = state != null ? state.selectedCustomerId : null;
            updateCustomerSpinnerSelection(selectedCustomerId);
        });

        viewModel.getStoreList().observe(getViewLifecycleOwner(), list -> {
            PetDetailViewModel.ViewState state = viewModel.getViewState().getValue();
            boolean staffCreating = isStaff() && (state == null || !state.isEditing);
            boolean storeEnabled = state == null || state.isStoreEnabled;
            Long selectedStoreId = (staffCreating && storeEnabled) ? tokenManager.getPrimaryStoreId() : (state != null ? state.selectedStoreId : null);
            updateStoreSpinnerSelection(selectedStoreId);
            if (staffCreating && storeEnabled) binding.spinnerStore.setEnabled(false);
        });

        viewModel.getSpeciesList().observe(getViewLifecycleOwner(), list -> {
            PetDetailViewModel.ViewState state = viewModel.getViewState().getValue();
            String selectedSpecies = state != null ? state.selectedSpecies : null;
            SpinnerUtils.populateSpinner(requireContext(), binding.spinnerPetSpecies, list,
                    DropdownDTO::getLabel, "-- Select Species --", null, DropdownDTO::getId);
            SpinnerUtils.setSelectionByValue(binding.spinnerPetSpecies, selectedSpecies);
        });
    }

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

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

    private void savePet() {
        if (!InputValidator.isNotEmpty(binding.etPetName, "Pet Name")) return;
        if (!InputValidator.isSpinnerSelected(binding.spinnerPetSpecies, "Species")) return;
        if (!InputValidator.isNotEmpty(binding.etPetBreed, "Breed")) return;
        if (!InputValidator.isPositiveInteger(binding.etPetAge, "Age")) return;
        if (!InputValidator.isPositiveDecimal(binding.etPetPrice, "Price")) return;

        String name = binding.etPetName.getText().toString().trim();
        List<DropdownDTO> speciesOptions = viewModel.getSpeciesList().getValue();
        String species = (speciesOptions != null && binding.spinnerPetSpecies.getSelectedItemPosition() > 0)
                ? speciesOptions.get(binding.spinnerPetSpecies.getSelectedItemPosition() - 1).getLabel()
                : "";
        String breed = binding.etPetBreed.getText().toString().trim();
        int age = Integer.parseInt(binding.etPetAge.getText().toString().trim());
        double price = Double.parseDouble(binding.etPetPrice.getText().toString().trim());
        String status = binding.spinnerPetStatus.getSelectedItem().toString();

        Long customerId = null;
        if (binding.spinnerCustomer.getSelectedItemPosition() > 0 && viewModel.getCustomerList().getValue() != null) {
            customerId = viewModel.getCustomerList().getValue().get(binding.spinnerCustomer.getSelectedItemPosition() - 1).getId();
        }

        Long storeId = null;
        if (binding.spinnerStore.getSelectedItemPosition() > 0 && viewModel.getStoreList().getValue() != null) {
            storeId = viewModel.getStoreList().getValue().get(binding.spinnerStore.getSelectedItemPosition() - 1).getId();
        }

        if ("Available".equalsIgnoreCase(status)) {
            if (!InputValidator.isSpinnerSelected(binding.spinnerStore, "Store")) return;
        }
        if ("Owned".equalsIgnoreCase(status)) {
            if (!InputValidator.isSpinnerSelected(binding.spinnerCustomer, "Owner")) return;
        }
        if ("Adopted".equalsIgnoreCase(status)) {
            if (!InputValidator.isSpinnerSelected(binding.spinnerCustomer, "Owner")) return;
            if (!InputValidator.isSpinnerSelected(binding.spinnerStore, "Store")) return;
        }

        PetDTO petDTO = new PetDTO();
        petDTO.setPetName(name);
        petDTO.setPetSpecies(species);
        petDTO.setPetBreed(breed);
        petDTO.setPetAge(age);
        petDTO.setPetPrice(price);
        petDTO.setPetStatus(status);
        petDTO.setCustomerId(customerId);
        petDTO.setStoreId(storeId);

        viewModel.savePet(petDTO).observe(getViewLifecycleOwner(), resource -> {
            if (resource == null) return;
            setLoading(resource.status == Resource.Status.LOADING);
            if (resource.status == Resource.Status.SUCCESS) {
                if (viewModel.isEditing()) {
                    ActivityLogger.logChange(requireContext(), "Pet", "UPDATED", (int) viewModel.getPetId());
                    Toast.makeText(getContext(), "Pet updated successfully!", Toast.LENGTH_SHORT).show();
                } else {
                    ActivityLogger.log(requireContext(), "Added new Pet: " + name);
                    Toast.makeText(getContext(), "Pet added successfully!", Toast.LENGTH_SHORT).show();
                }
                navigateToPetList();
            } else if (resource.status == Resource.Status.ERROR) {
                Toast.makeText(getContext(), "Error: " + resource.message, Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void deletePet() {
        DialogUtils.showDeleteConfirmDialog(requireContext(), "Pet", () -> {
                viewModel.deletePet().observe(getViewLifecycleOwner(), resource -> {
                    if (resource == null) return;
                    setLoading(resource.status == Resource.Status.LOADING);
                    if (resource.status == Resource.Status.SUCCESS) {
                        ActivityLogger.logChange(requireContext(), "Pet", "DELETED", (int) viewModel.getPetId());
                        Toast.makeText(getContext(), "Pet deleted successfully!", Toast.LENGTH_SHORT).show();
                        navigateToPetList();
                    } else if (resource.status == Resource.Status.ERROR) {
                        Toast.makeText(getContext(), "Delete failed: " + resource.message, Toast.LENGTH_SHORT).show();
                    }
                });
        });
    }

    private void navigateToPetList() {
        NavHostFragment.findNavController(this).popBackStack(R.id.nav_pet, false);
    }

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

    private void handleArguments() {
        if (getArguments() != null && getArguments().containsKey("petId")) {
            viewModel.setPetId(getArguments().getLong("petId"));
            loadPetData();
            return;
        }

        viewModel.setPetId(-1);
    }

    private void loadPetData() {
        viewModel.loadPet().observe(getViewLifecycleOwner(), resource -> {
            if (resource == null) return;
            setLoading(resource.status == Resource.Status.LOADING);
            if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
                PetDTO p = resource.data;
                binding.etPetName.setText(p.getPetName());
                binding.etPetBreed.setText(p.getPetBreed());
                binding.etPetAge.setText(String.valueOf(p.getPetAge()));
                if (p.getPetPrice() != null) {
                    binding.etPetPrice.setText(String.format(Locale.getDefault(), "%.2f", p.getPetPrice()));
                }
            } else if (resource.status == Resource.Status.ERROR) {
                Toast.makeText(getContext(), "Failed to load pet: " + resource.message, Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void updateCustomerSpinnerSelection(Long selectedCustomerId) {
        SpinnerUtils.populateSpinner(
                requireContext(),
                binding.spinnerCustomer,
                viewModel.getCustomerList().getValue(),
                DropdownDTO::getLabel,
                "No Owner",
                selectedCustomerId,
                DropdownDTO::getId
        );
    }

    private void updateStoreSpinnerSelection(Long selectedStoreId) {
        SpinnerUtils.populateSpinner(
                requireContext(),
                binding.spinnerStore,
                viewModel.getStoreList().getValue(),
                DropdownDTO::getLabel,
                "None",
                selectedStoreId,
                DropdownDTO::getId
        );
    }

    private void setupSpinner() {
        SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerPetStatus, new String[]{});

        SpinnerUtils.setOnIndexSelectedListener(binding.spinnerPetSpecies, p -> {
            if (isUpdatingUI) return;
            viewModel.onSpeciesSelected(p);
        });

        binding.spinnerCustomer.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                if (isUpdatingUI) return;
                viewModel.onCustomerSelected(position);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

        binding.spinnerStore.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                if (isUpdatingUI) return;
                viewModel.onStoreSelected(position);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

        binding.spinnerPetStatus.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                if (isUpdatingUI) return;
                String status = parent.getItemAtPosition(position).toString();
                clearSpinnerError(binding.spinnerCustomer);
                clearSpinnerError(binding.spinnerStore);
                viewModel.onStatusSelected(status);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
    }

    private void applyViewState(PetDetailViewModel.ViewState state) {
        isUpdatingUI = true;

        binding.tvMode.setText(state.modeTitle);
        binding.tvPetId.setText(DateTimeUtils.formatId(viewModel.getPetId()));
        binding.tvPetId.setVisibility(state.isPetIdVisible ? View.VISIBLE : View.GONE);
        binding.btnDeletePet.setVisibility(state.isDeleteVisible ? View.VISIBLE : View.GONE);
        binding.btnSavePet.setText(state.saveButtonText);

        UIUtils.setViewsEnabled(state.isSpeciesEnabled, binding.spinnerPetSpecies);
        UIUtils.setViewsEnabled(state.isBreedEnabled, binding.etPetBreed);
        UIUtils.setViewsEnabled(state.isCustomerEnabled, binding.spinnerCustomer);
        UIUtils.setViewsEnabled(state.isStoreEnabled, binding.spinnerStore);

        SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerPetStatus, state.availableStatuses);
        SpinnerUtils.setSelectionByValue(binding.spinnerPetStatus, state.selectedStatus);

        updateCustomerSpinnerSelection(state.selectedCustomerId);
        updateStoreSpinnerSelection(state.selectedStoreId);

        List<DropdownDTO> species = viewModel.getSpeciesList().getValue();
        if (species != null) {
            SpinnerUtils.populateSpinner(requireContext(), binding.spinnerPetSpecies, species,
                    DropdownDTO::getLabel, "-- Select Species --", null, DropdownDTO::getId);
            SpinnerUtils.setSelectionByValue(binding.spinnerPetSpecies, state.selectedSpecies);
        }

        if (!state.isCustomerEnabled && binding.spinnerCustomer.getSelectedItemPosition() != 0) {
            binding.spinnerCustomer.setSelection(0);
        }
        if (!state.isStoreEnabled && binding.spinnerStore.getSelectedItemPosition() != 0) {
            binding.spinnerStore.setSelection(0);
        }

        if (isStaff() && !state.isEditing && state.isStoreEnabled) {
            updateStoreSpinnerSelection(tokenManager.getPrimaryStoreId());
            binding.spinnerStore.setEnabled(false);
        }

        isUpdatingUI = false;
    }

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

    private void clearSpinnerError(Spinner spinner) {
        View selectedView = spinner.getSelectedView();
        if (selectedView instanceof TextView) {
            ((TextView) selectedView).setError(null);
        }
    }
}
