package com.prank.funnypranksounds.ui.fragment;

import static android.app.Activity.RESULT_OK;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.ItemTouchHelper;

import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.prank.funnypranksounds.R;
import com.prank.funnypranksounds.data.local.entity.AudioData;
import com.prank.funnypranksounds.data.repository.AudioRepository;
import com.prank.funnypranksounds.databinding.FragmentAudioBinding;
import com.prank.funnypranksounds.ui.activity.RecordAudioActivity;
import com.prank.funnypranksounds.ui.adapter.AudioAdapter;
import com.prank.funnypranksounds.ui.callback.AudioItemCallback;
import com.prank.funnypranksounds.utils.AudioUtils;
import com.prank.funnypranksounds.viewmodel.AudioViewModel;

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

public class AudioFragment extends Fragment implements AudioItemCallback.OnItemSwipeListener {

    private FragmentAudioBinding binding;
    private AudioAdapter adapter;
    private AudioViewModel audioViewModel;
    private Uri audioUri;
    private String fileName;
    private List<AudioData> audioDataList = new ArrayList<>();
    private static final int REQUEST_CODE_READ_MEDIA_AUDIO = 1001;
    private static final int REQUEST_CODE_PICK_AUDIO = 1002;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        binding = FragmentAudioBinding.inflate(inflater, container, false);

        initData();
        initEvent();

        return binding.getRoot();
    }

    private void initData() {
        audioViewModel = new ViewModelProvider(this, new ViewModelProvider.AndroidViewModelFactory(requireActivity().getApplication()))
                .get(AudioViewModel.class);


        binding.recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 1));
        adapter = new AudioAdapter(audioDataList, audioViewModel, requireContext(), requireActivity(), 1);
        binding.recyclerView.setAdapter(adapter);

        AudioItemCallback callback = new AudioItemCallback(this);
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);
        itemTouchHelper.attachToRecyclerView(binding.recyclerView);
    }

    private void initEvent() {
        binding.add.setOnClickListener(v -> showCustomBottomSheetDialog());
        loadExternal();
    }

    private void loadExternal() {
        audioViewModel
                .getExternal()
                .observe(getViewLifecycleOwner(), new Observer<List<AudioData>>() {
                    @Override
                    public void onChanged(List<AudioData> dataList) {
                        ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) binding.add.getLayoutParams();
                        if (dataList.isEmpty()) {
                            binding.audioBackground.setVisibility(View.VISIBLE);

                            layoutParams.topToBottom = ConstraintLayout.LayoutParams.UNSET;
                            layoutParams.bottomToTop = ConstraintLayout.LayoutParams.UNSET;
                            layoutParams.topToTop = ConstraintLayout.LayoutParams.PARENT_ID;
                        } else {
                            binding.audioBackground.setVisibility(View.GONE);

                            layoutParams.topToTop = ConstraintLayout.LayoutParams.UNSET;
                            layoutParams.bottomToTop = ConstraintLayout.LayoutParams.UNSET;
                            layoutParams.topToBottom = R.id.recycler_view;
                        }
                        layoutParams.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID;
                        layoutParams.startToStart = ConstraintLayout.LayoutParams.PARENT_ID;
                        layoutParams.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID;
                        audioDataList = dataList;
                        adapter.updateData(dataList);
                    }
                });
    }

    private void showCustomBottomSheetDialog() {
        BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(requireContext());
        View dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.bottom_dialog, null);

        bottomSheetDialog.setCanceledOnTouchOutside(false);

        dialogView.findViewById(R.id.import_audio).setOnClickListener(v -> {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                openAudioPicker();
            } else {
                if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_EXTERNAL_STORAGE)
                        != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(requireActivity(),
                            new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                            REQUEST_CODE_READ_MEDIA_AUDIO);
                } else {
                    openAudioPicker();
                }
            }
            bottomSheetDialog.dismiss();
        });

        dialogView.findViewById(R.id.create).setOnClickListener(v -> {
            Intent intent = new Intent(getActivity(), RecordAudioActivity.class);
            startActivity(intent);
            bottomSheetDialog.dismiss();
        });

        dialogView.findViewById(R.id.cancel_button).setOnClickListener(v -> {
            bottomSheetDialog.dismiss();
        });

        bottomSheetDialog.setContentView(dialogView);
        bottomSheetDialog.show();
    }

    private void openAudioPicker() {
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent.setType("audio/*");
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        startActivityForResult(intent, REQUEST_CODE_PICK_AUDIO);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE_READ_MEDIA_AUDIO) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                openAudioPicker();
            } else {
                Toast.makeText(requireContext(), "Permission denied", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode != REQUEST_CODE_PICK_AUDIO || resultCode != RESULT_OK || data == null) {
            return;
        }

        audioUri = data.getData();
        if (audioUri == null) {
            Toast.makeText(requireContext(), "The file could not be found.", Toast.LENGTH_LONG).show();
            return;
        }

        fileName = AudioUtils.getFileName(audioUri, requireActivity());

        try {
            audioViewModel.getCountAsync(audioUri.toString(), new AudioRepository.CountCallback() {
                @Override
                public void onCountFetched(int count) {
                    if (count > 0) {
                        Toast.makeText(requireContext(), "This file has been imported and cannot be imported again", Toast.LENGTH_LONG).show();
                    } else {
                        audioViewModel.insert(new AudioData(fileName, audioUri.toString(), fileName, audioUri.toString(), "", false, true));
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(requireContext(), "Failed to insert database: " + e.getMessage(), Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public void onItemSwiped(int position) {
        deleteItem(position);
    }

    public void deleteItem(int position) {
        AudioData audioData = audioDataList.get(position);
        try {
            audioViewModel.delete(audioData);
            Toast.makeText(getContext(), "Audio deleted successfully.", Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            Toast.makeText(getContext(), "Failed to delete audio.", Toast.LENGTH_SHORT).show();
        }
    }

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