package com.example.petstoremobile.fragments;

import android.net.Uri;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.Toast;

import com.example.petstoremobile.R;
import com.example.petstoremobile.activities.MainActivity;
import com.example.petstoremobile.api.auth.AuthApi;
import com.example.petstoremobile.api.auth.TokenManager;
import com.example.petstoremobile.databinding.FragmentProfileBinding;
import com.example.petstoremobile.dtos.UserDTO;
import com.example.petstoremobile.services.ChatNotificationService;
import com.example.petstoremobile.utils.FileUtils;
import com.example.petstoremobile.utils.GlideUtils;
import com.example.petstoremobile.utils.ImagePickerHelper;
import com.example.petstoremobile.utils.InputValidator;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.UIUtils;
import com.example.petstoremobile.viewmodels.AuthViewModel;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import javax.inject.Inject;
import javax.inject.Named;

import dagger.hilt.android.AndroidEntryPoint;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;

/**
 * Fragment that displays and allows editing of the user's profile information.
 */
@AndroidEntryPoint
public class ProfileFragment extends Fragment {

    private FragmentProfileBinding binding;
    private UserDTO currentUser;
    private AuthViewModel viewModel;
    private boolean hasImage = false;

    @Inject TokenManager tokenManager;
    @Inject @Named("baseUrl") String baseUrl;

    private ImagePickerHelper imagePickerHelper;

    /**
     * Initializes activity launchers and the ImagePickerHelper for camera and gallary.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        viewModel = new ViewModelProvider(this).get(AuthViewModel.class);

        imagePickerHelper = new ImagePickerHelper(this, "profile_photo.jpg", new ImagePickerHelper.ImagePickerListener() {
            @Override
            public void onImagePicked(Uri uri) {
                uploadAvatar(uri);
            }

            @Override
            public void onImageRemoved() {
                deleteAvatar();
            }
        });
    }

    /**
     * Inflates the fragment layout and sets up listeners for profile.
     */
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        binding = FragmentProfileBinding.inflate(inflater, container, false);

        //Load Profile Data from backend
        loadProfileData();

        //Set up listeners for the buttons
        //Change photo button
        binding.btnChangePhoto.setOnClickListener(v -> {
            imagePickerHelper.showImagePickerDialog("Change Profile Photo", hasImage);
        });

        //Edit email button
        //When clicked open a dialog to change email
        binding.btnEditEmail.setOnClickListener(v -> {
            //Make a text field for the user to enter the new email
            EditText input = new EditText(requireContext());
            input.setPadding(30,30,30,30);
            input.setText(binding.tvProfileEmail.getText().toString());

            //set input type to email
            input.setInputType(android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);


            //Show alert dialog to user to enter new email
            new AlertDialog.Builder(requireContext())
                    .setTitle("Edit Email")
                    .setView(input)
                    .setPositiveButton("Save", (dialog, which) -> {
                        if (InputValidator.isValidEmail(input)) {
                            updateProfileField("email", input.getText().toString());
                        } else {
                            Toast.makeText(requireContext(), "Email is invalid", Toast.LENGTH_SHORT).show();
                        }
                    })
                    .setNegativeButton("Cancel", null)
                    .show();
        });

        //Edit phone button
        //When clicked open a dialog to change phone
        binding.btnEditPhone.setOnClickListener(v -> {
            //Make a text field for the user to enter the new email
            EditText input = new EditText(requireContext());
            input.setPadding(30,30,30,30);
            input.setText(binding.tvProfilePhone.getText().toString());

            //set input type to phone number
            input.setInputType(android.view.inputmethod.EditorInfo.TYPE_CLASS_PHONE);

            //add canada phone number formatting to input
            UIUtils.formatPhoneInput(input);


            //Show alert dialog to user to enter new phone
            new AlertDialog.Builder(requireContext())
                    .setTitle("Edit Phone Number")
                    .setView(input)
                    .setPositiveButton("Save", (dialog, which) -> {
                        if (InputValidator.isValidPhone(input)) {
                            updateProfileField("phone", input.getText().toString());
                        } else {
                            Toast.makeText(requireContext(), "Phone number is invalid", Toast.LENGTH_SHORT).show();
                        }
                    })
                    .setNegativeButton("Cancel", null)
                    .show();
        });

        //Logout button
        binding.btnLogout.setOnClickListener(v -> {
            // Stop notification service before logging out so notifications stop
            android.content.Intent serviceIntent = new android.content.Intent(requireContext(), ChatNotificationService.class);
            requireContext().stopService(serviceIntent);

            // clear the token for next login
            tokenManager.clearLoginData();
            //get the intent to the main activity and clear the back stack so the back button won't allow the user to go back to the previous screen
            android.content.Intent intent = new android.content.Intent(getActivity(), MainActivity.class);
            intent.addFlags(android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP | android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
            //start the activity to go to login page and finish the current activity
            startActivity(intent);
            requireActivity().finish();
        });

        return binding.getRoot();
    }

    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;
    }

    /**
     * Fetches current user profile data from the API and then updates the UI.
     */
    private void loadProfileData() {
        viewModel.getMe().observe(getViewLifecycleOwner(), resource -> {
            if (resource == null) return;
            setLoading(resource.status == Resource.Status.LOADING);
            if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
                currentUser = resource.data;

                //set the user data to the view
                binding.tvProfileName.setText(currentUser.getFullName());
                binding.tvProfileEmail.setText(currentUser.getEmail());
                binding.tvProfilePhone.setText(currentUser.getPhone());
                binding.tvProfileRole.setText(currentUser.getRole());

                // get the avatar endpoint to load profile image and the token for authorization
                String avatarUrl = baseUrl + AuthApi.AVATAR_FILE_PATH;
                String token = tokenManager.getToken();

                GlideUtils.loadImageWithToken(requireContext(), binding.imgProfile, avatarUrl, token, R.drawable.placeholder, new GlideUtils.ImageLoadListener() {
                    @Override
                    public void onResourceReady() {
                        hasImage = true;
                    }

                    @Override
                    public void onLoadFailed() {
                        hasImage = false;
                    }
                });
            } else if (resource.status == Resource.Status.ERROR) {
                Toast.makeText(getContext(), "Failed to load profile: " + resource.message, Toast.LENGTH_SHORT).show();
            }
        });
    }

    /**
     * Uploads the selected or captured image as the user's new avatar.
     */
    private void uploadAvatar(Uri uri) {
        try {
            File file = FileUtils.getFileFromUri(requireContext(), uri);
            if (file == null) return;
            
            // Create RequestBody for file upload
            RequestBody requestFile = RequestBody.create(file, MediaType.parse(requireContext().getContentResolver().getType(uri)));
            MultipartBody.Part body = MultipartBody.Part.createFormData("avatar", file.getName(), requestFile);

            //Call the backend to upload the avatar
            viewModel.uploadAvatar(body).observe(getViewLifecycleOwner(), resource -> {
                if (resource == null) return;
                setLoading(resource.status == Resource.Status.LOADING);
                if (resource.status == Resource.Status.SUCCESS) {
                    Toast.makeText(getContext(), "Avatar updated successfully", Toast.LENGTH_SHORT).show();
                    loadProfileData();
                } else if (resource.status == Resource.Status.ERROR) {
                    Toast.makeText(getContext(), "Upload failed: " + resource.message, Toast.LENGTH_SHORT).show();
                }
            });
        } catch (Exception e) {
            Log.e("UPLOAD_AVATAR", "Error: " + e.getMessage());
        }
    }

    /**
     * Sends a request to the API to delete the current user's avatar image.
     */
    private void deleteAvatar() {
        viewModel.deleteAvatar().observe(getViewLifecycleOwner(), resource -> {
            if (resource == null) return;
            setLoading(resource.status == Resource.Status.LOADING);
            if (resource.status == Resource.Status.SUCCESS) {
                hasImage = false;
                binding.imgProfile.setImageResource(R.drawable.placeholder);
                Toast.makeText(getContext(), "Avatar removed successfully", Toast.LENGTH_SHORT).show();
            } else if (resource.status == Resource.Status.ERROR) {
                Toast.makeText(getContext(), "Removal failed: " + resource.message, Toast.LENGTH_SHORT).show();
            }
        });
    }

    /**
     * Updates a specific profile field (like email or phone) by sending a request to the API.
     */
    private void updateProfileField(String fieldName, String value) {
        Map<String, String> updates = new HashMap<>();
        updates.put(fieldName, value);

        viewModel.updateMe(updates).observe(getViewLifecycleOwner(), resource -> {
            if (resource == null) return;
            setLoading(resource.status == Resource.Status.LOADING);
            if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
                currentUser = resource.data;
                Toast.makeText(getContext(), "Profile updated successfully", Toast.LENGTH_SHORT).show();
                // Update the view with the new data from backend
                binding.tvProfileEmail.setText(currentUser.getEmail());
                binding.tvProfilePhone.setText(currentUser.getPhone());
            } else if (resource.status == Resource.Status.ERROR) {
                Toast.makeText(getContext(), "Update failed: " + resource.message, Toast.LENGTH_SHORT).show();
            }
        });
    }
}
