package com.example.petstoremobile.viewmodels;

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

import com.example.petstoremobile.dtos.DropdownDTO;
import com.example.petstoremobile.dtos.PetDTO;
import com.example.petstoremobile.repositories.CustomerRepository;
import com.example.petstoremobile.repositories.PetRepository;
import com.example.petstoremobile.repositories.StoreRepository;
import com.example.petstoremobile.utils.Resource;

import androidx.lifecycle.Observer;

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

import javax.inject.Inject;

import dagger.hilt.android.lifecycle.HiltViewModel;

@HiltViewModel
public class PetDetailViewModel extends ViewModel {
    private static final String STATUS_AVAILABLE = "Available";
    private static final String STATUS_ADOPTED = "Adopted";
    private static final String STATUS_OWNED = "Owned";
    private static final String STATUS_PENDING = "Pending";

    private final PetRepository petRepository;
    private final CustomerRepository customerRepository;
    private final StoreRepository storeRepository;

    private final MutableLiveData<List<DropdownDTO>> customerList = new MutableLiveData<>(new ArrayList<>());
    private final MutableLiveData<List<DropdownDTO>> storeList = new MutableLiveData<>(new ArrayList<>());
    private final MutableLiveData<List<DropdownDTO>> speciesList = new MutableLiveData<>(new ArrayList<>());
    private final MutableLiveData<List<DropdownDTO>> breedList = new MutableLiveData<>(new ArrayList<>());
    private final MutableLiveData<Boolean> isLoading = new MutableLiveData<>(false);
    private final MutableLiveData<ViewState> viewState = new MutableLiveData<>(new ViewState());

    private long petId = -1;
    private Long selectedCustomerId = null;
    private Long selectedStoreId = null;
    private String selectedSpecies = null;
    private String selectedBreed = null;
    private boolean isOriginallyOwnedOrAdopted = false;
    private Long originalCustomerId = null;

    @Inject
    public PetDetailViewModel(PetRepository petRepository, CustomerRepository customerRepository, StoreRepository storeRepository) {
        this.petRepository = petRepository;
        this.customerRepository = customerRepository;
        this.storeRepository = storeRepository;
    }

    public void loadInitialFormData() {
        observeOnce(customerRepository.getCustomerDropdowns(), resource -> {
            if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
                customerList.setValue(resource.data);
            }
        });

        observeOnce(storeRepository.getStoreDropdowns(), resource -> {
            if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
                storeList.setValue(resource.data);
            }
        });

        observeOnce(petRepository.getPetSpeciesDropdowns(), resource -> {
            if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
                speciesList.setValue(resource.data);
            }
        });
    }

    public void setPetId(long id) {
        this.petId = id;
        initMode(id != -1);
    }

    public long getPetId() {
        return petId;
    }

    public boolean isEditing() {
        ViewState current = viewState.getValue();
        return current != null && current.isEditing;
    }

    public boolean isOriginallyOwnedOrAdopted() {
        return isOriginallyOwnedOrAdopted;
    }

    public Long getOriginalCustomerId() {
        return originalCustomerId;
    }

    public LiveData<ViewState> getViewState() {
        return viewState;
    }

    public void onCustomerSelected(int position) {
        List<DropdownDTO> list = customerList.getValue();
        if (position > 0 && list != null && position <= list.size()) {
            selectedCustomerId = list.get(position - 1).getId();
        } else {
            selectedCustomerId = null;
        }

        updateViewState(state -> state.selectedCustomerId = selectedCustomerId);
    }

    public void onSpeciesSelected(int position) {
        List<DropdownDTO> list = speciesList.getValue();
        if (position > 0 && list != null && position <= list.size()) {
            selectedSpecies = list.get(position - 1).getLabel();
            loadBreeds(selectedSpecies);
        } else {
            selectedSpecies = null;
            breedList.setValue(new ArrayList<>());
        }
        updateViewState(state -> {
            state.selectedSpecies = selectedSpecies;
            state.isBreedEnabled = !state.isEditing && (selectedSpecies != null);
        });
    }

    public void onBreedSelected(int position) {
        List<DropdownDTO> list = breedList.getValue();
        if (position > 0 && list != null && position <= list.size()) {
            selectedBreed = list.get(position - 1).getLabel();
        } else {
            selectedBreed = null;
        }
        updateViewState(state -> state.selectedBreed = selectedBreed);
    }

    private void loadBreeds(String species) {
        observeOnce(petRepository.getPetBreedsDropdowns(species), resource -> {
            if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
                breedList.setValue(resource.data);
            }
        });
    }

    public void onStoreSelected(int position) {
        List<DropdownDTO> list = storeList.getValue();
        if (position > 0 && list != null && position <= list.size()) {
            selectedStoreId = list.get(position - 1).getId();
        } else {
            selectedStoreId = null;
        }

        updateViewState(state -> state.selectedStoreId = selectedStoreId);
    }

    public void onStatusSelected(String status) {
        updateViewState(state -> {
            state.selectedStatus = normalizeStatus(status);
            applyStatusRules(state, true);
        });
    }

    public void initMode(boolean isEditing) {
        updateViewState(state -> {
            state.isEditing = isEditing;
            state.modeTitle = isEditing ? "Edit Pet" : "Add Pet";
            state.saveButtonText = isEditing ? "Save" : "Add";
            state.isPetIdVisible = isEditing;
            state.isDeleteVisible = isEditing;
            state.isSpeciesEnabled = !isEditing;
            state.isBreedEnabled = !isEditing;

            if (isEditing) {
                state.isCustomerEnabled = true;
                state.isStoreEnabled = true;
            }

            if (!isEditing) {
                selectedCustomerId = null;
                selectedStoreId = null;
                selectedSpecies = null;
                selectedBreed = null;
                state.selectedCustomerId = null;
                state.selectedStoreId = null;
                state.selectedSpecies = null;
                state.selectedBreed = null;
                state.selectedStatus = STATUS_AVAILABLE;
                state.isCustomerEnabled = false;
                state.isStoreEnabled = true;
                state.isBreedEnabled = false;
            }
        });
    }

    public LiveData<Resource<PetDTO>> loadPet() {
        MutableLiveData<Resource<PetDTO>> result = new MutableLiveData<>();
        observeOnce(petRepository.getPetById(petId), resource -> {
            if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
                PetDTO pet = resource.data;
                selectedCustomerId = pet.getCustomerId();
                selectedStoreId = pet.getStoreId();
                selectedSpecies = pet.getPetSpecies();
                selectedBreed = pet.getPetBreed();
                isOriginallyOwnedOrAdopted = STATUS_OWNED.equalsIgnoreCase(pet.getPetStatus())
                        || STATUS_ADOPTED.equalsIgnoreCase(pet.getPetStatus());
                originalCustomerId = pet.getCustomerId();

                if (selectedSpecies != null) {
                    loadBreeds(selectedSpecies);
                }

                updateViewState(state -> {
                    state.selectedCustomerId = selectedCustomerId;
                    state.selectedStoreId = selectedStoreId;
                    state.selectedSpecies = selectedSpecies;
                    state.selectedBreed = selectedBreed;
                    state.selectedStatus = normalizeStatus(pet.getPetStatus());
                    state.isBreedEnabled = !state.isEditing && (selectedSpecies != null);
                    applyStatusRules(state, false);
                });
            }

            result.setValue(resource);
        });
        return result;
    }

    public LiveData<Resource<PetDTO>> savePet(PetDTO petDTO) {
        if (isEditing()) {
            petDTO.setPetId(petId);
            return petRepository.updatePet(petId, petDTO);
        }

        return petRepository.createPet(petDTO);
    }

    public LiveData<Resource<Void>> deletePet() {
        return petRepository.deletePet(petId);
    }

    public LiveData<Resource<Void>> uploadPetImage(okhttp3.MultipartBody.Part image) {
        return petRepository.uploadPetImage(petId, image);
    }

    public LiveData<Resource<Void>> deletePetImage() {
        return petRepository.deletePetImage(petId);
    }

    public LiveData<List<DropdownDTO>> getCustomerList() {
        return customerList;
    }

    public LiveData<List<DropdownDTO>> getStoreList() {
        return storeList;
    }

    public LiveData<List<DropdownDTO>> getSpeciesList() {
        return speciesList;
    }

    public LiveData<List<DropdownDTO>> getBreedList() {
        return breedList;
    }

    public LiveData<Boolean> getIsLoading() {
        return isLoading;
    }

    public void setLoading(boolean loading) {
        isLoading.setValue(loading);
    }

    private void applyStatusRules(ViewState state, boolean clearInvalidSelections) {
        if (STATUS_AVAILABLE.equalsIgnoreCase(state.selectedStatus)) {
            state.isCustomerEnabled = false;
            state.isStoreEnabled = true;
            if (clearInvalidSelections) {
                selectedCustomerId = null;
                state.selectedCustomerId = null;
            }
            return;
        }

        if (STATUS_OWNED.equalsIgnoreCase(state.selectedStatus)) {
            state.isCustomerEnabled = true;
            state.isStoreEnabled = false;
            if (clearInvalidSelections) {
                selectedStoreId = null;
                state.selectedStoreId = null;
            }
            return;
        }

        state.isCustomerEnabled = true;
        state.isStoreEnabled = true;
    }

    private String normalizeStatus(String status) {
        if (status == null) return STATUS_AVAILABLE;
        String normalized = status.trim();
        if (STATUS_ADOPTED.equalsIgnoreCase(normalized)) return STATUS_ADOPTED;
        if (STATUS_OWNED.equalsIgnoreCase(normalized)) return STATUS_OWNED;
        if (STATUS_PENDING.equalsIgnoreCase(normalized)) return STATUS_PENDING;
        return STATUS_AVAILABLE;
    }

    private void updateViewState(Action<ViewState> action) {
        ViewState current = viewState.getValue();
        if (current != null) {
            action.run(current);
            viewState.setValue(current);
        }
    }

    private interface Action<T> {
        void run(T target);
    }

    private <T> void observeOnce(LiveData<Resource<T>> liveData, Observer<Resource<T>> handler) {
        liveData.observeForever(new Observer<Resource<T>>() {
            @Override
            public void onChanged(Resource<T> resource) {
                if (resource == null || resource.status != Resource.Status.LOADING) {
                    liveData.removeObserver(this);
                }
                handler.onChanged(resource);
            }
        });
    }

    public static class ViewState {
        public boolean isEditing = false;
        public boolean isDeleteVisible = false;
        public boolean isPetIdVisible = false;
        public boolean isSpeciesEnabled = true;
        public boolean isBreedEnabled = true;
        public boolean isCustomerEnabled = false;
        public boolean isStoreEnabled = true;
        public String modeTitle = "Add Pet";
        public String saveButtonText = "Add";
        public String[] availableStatuses = new String[]{STATUS_AVAILABLE, STATUS_ADOPTED, STATUS_OWNED, STATUS_PENDING};
        public String selectedStatus = STATUS_AVAILABLE;
        public String selectedSpecies = null;
        public String selectedBreed = null;
        public Long selectedCustomerId = null;
        public Long selectedStoreId = null;
    }
}
