package com.utopiaindustries.qualitychecker.ui.fragments;

import static android.app.Activity.RESULT_OK;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.bumptech.glide.Glide;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.utopiaindustries.qualitychecker.R;
import com.utopiaindustries.qualitychecker.async.ImageProcessor;
import com.utopiaindustries.qualitychecker.models.callback.SaveDraftReportCallback;
import com.utopiaindustries.qualitychecker.models.callback.SaveReportCallback;
import com.utopiaindustries.qualitychecker.notification.NotificationHelper;
import com.utopiaindustries.qualitychecker.service.InspectionReportService;
import com.utopiaindustries.qualitychecker.store.Store;
import com.utopiaindustries.qualitychecker.ui.adapter.CheckPointAdapter;
import com.utopiaindustries.qualitychecker.utils.FileUtils;
import com.utopiaindustries.qualitychecker.utils.ImageUriHolder;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;

public class SecondStepFragment extends Fragment
        implements View.OnClickListener {

    private NavController navController;
    private Button leftFab, rightFab, draftFab, moveToBottom;
    private RecyclerView recyclerView;
    private CheckPointAdapter adapter;
    private TextView profileName;
    private ImageView profileImage;
    private InspectionReportService inspectionReportService;
    private Store store;
    private static final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 100;
    private static final int MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 101;
    private static final int MY_PERMISSIONS_REQUEST_CAMERA = 102;
    List<byte[]> temp_path = new ArrayList<>();
    private HashMap<String, List<String>> imagesMap = new HashMap<>();

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_second_step, container, false);

        store = Store.getInstance();
        inspectionReportService = InspectionReportService.getInstance();
        draftFab = view.findViewById(R.id.button_draft_second);
        leftFab = view.findViewById(R.id.button_left_frag_2);
        rightFab = view.findViewById(R.id.button_right_frag_2);
        moveToBottom = view.findViewById(R.id.button_move_to_bottom);
        recyclerView = view.findViewById(R.id.check_point_recycler_view);
        profileName = view.findViewById(R.id.second_profile_name);
        profileImage = view.findViewById(R.id.second_step_profile_image);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));

        // PERMISSIONS
        {
            // Check if permission is not granted
            if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE)
                    != PackageManager.PERMISSION_GRANTED) {

                // Permission is not granted, request it
                ActivityCompat.requestPermissions(getActivity(),
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
            }

            if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    != PackageManager.PERMISSION_GRANTED) {

                ActivityCompat.requestPermissions(getActivity(),
                        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
            }

            if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA)
                    != PackageManager.PERMISSION_GRANTED) {

                ActivityCompat.requestPermissions(getActivity(),
                        new String[]{Manifest.permission.CAMERA},
                        MY_PERMISSIONS_REQUEST_CAMERA);
            }
        }

        adapter = new CheckPointAdapter(store.getReport().getItems().get(0).getCheckPoints(),
                store.getCheckPoints(),
                store.getDefects(),
                inspectionReportService.getDefectTypes(),
                store.getCheckpointSkus(),
                getContext());
        recyclerView.setAdapter(adapter);
        // set on click listener
        leftFab.setOnClickListener(this);
        rightFab.setOnClickListener(this);
        draftFab.setOnClickListener(this);
        moveToBottom.setOnClickListener(this);
        updateProfileViews();
        return view;
    }

    @Override
    public void onClick(View v) {
        navController = Navigation.findNavController(requireView());

        if (v.getId() == R.id.button_draft_second) {
            //System.out.println("Draft Button Click-1" + store.getReport());
            //--Storing draft report in database
            if (store.getReport() != null) {
                //System.out.println("Draft Button Click-2");
                inspectionReportService.saveDraftInLocalDb(getContext(), store.getReport(), new SaveDraftReportCallback() {
                    @Override
                    public void onSuccess() {
                        //System.out.println("Draft Button Click-3");
                        Handler handler = new Handler(Looper.getMainLooper());
                        handler.post(() -> {
                            SharedPreferences sharedPreferences = getContext().getSharedPreferences("login_prefs", Context.MODE_PRIVATE);
                            SharedPreferences.Editor editor = sharedPreferences.edit();

                            editor.putString("draftReportId", "0");
                            editor.apply();
                            // progressBar.setVisibility(View.INVISIBLE);
                            Objects.requireNonNull(getActivity()).finish();
                            NotificationHelper.showNotification(Objects.requireNonNull(getContext()),
                                    "Utopia QA App",
                                    "Report is successfully drafted");

                            Toast.makeText(getContext(), "Report Saved as Draft", Toast.LENGTH_SHORT).show();
                        });
                    }

                    @Override
                    public void onFailure(Throwable throwable) {
                        System.out.println("Draft Button Click-4");
                        Handler handler = new Handler(Looper.getMainLooper());
                        handler.post(() -> {
                            Toast.makeText(getContext(), throwable.getMessage(), Toast.LENGTH_LONG).show();
                            //progressBar.setVisibility(View.INVISIBLE);
                            NotificationHelper.showNotification(Objects.requireNonNull(getContext()),
                                    "Utopia QA App",
                                    "Error in saving report");
                        });
                    }
                });
            }

            //---

        }
        if (v.getId() == R.id.button_left_frag_2) {
            navController.navigate(R.id.action_secondStepFragment_to_firstStepFragment);
        }
        if (v.getId() == R.id.button_right_frag_2) {
            checkIsRecyclerViewIsCompletelyScrolled(recyclerView);
        }

        if (v.getId() == R.id.button_move_to_bottom) {
            Log.e("Fab-Button","click");
            scrollToBottom();
        }
    }

    public void onImagePickerResult(int requestCode, int resultCode, Intent data) {
        if (requestCode != RESULT_OK) {
            try {
                System.out.println(requestCode);
                ImageProcessor imageProcessor = new ImageProcessor();
                /*Bitmap photo = (Bitmap) data.getExtras().get("data");
                assert photo != null;

                Uri selectedImageUri = FileUtils.getImageUriFromBitmap(requireContext(), photo);

                assert selectedImageUri != null;
                String imagePath = selectedImageUri.getPath();*/
                String imagePath = "";
                Uri selectedImageUri = null;

                if (data != null) {
                    Log.e("onImagePickerResult: ", "Gallery: " + data);
                    /*Bitmap photo = (Bitmap) data.getExtras().get("data");

                    assert photo != null;
                    selectedImageUri = FileUtils.getImageUriFromBitmap(requireContext(), photo);
                    imagePath = selectedImageUri.getPath();*/
                    selectedImageUri = data.getData();
                    assert selectedImageUri != null;
                    imagePath = selectedImageUri.getPath();
                } else {
                    Log.e("onImagePickerResult: ", "Camera");
                    selectedImageUri = ImageUriHolder.getInstance().getImageUri();
                    imagePath = selectedImageUri.getPath();
                }

                store.getReport().getItems().get(0).getCheckPoints().get(requestCode).setImagePath(imagePath);
                //store.getReport().getItems().get(0).getCheckPoints().get(requestCode).addImageList(uriToByteArray(getContext(), selectedImageUri));

                uriToByteArrayAsync(
                        getContext(),
                        selectedImageUri,
                        100,  // Target size in KB
                        compressedImage -> {
                            // Handle the compressed image here, e.g., display it
                            requireActivity().runOnUiThread(() -> {
                                store.getReport().getItems().get(0).getCheckPoints().get(requestCode).addImageList(compressedImage);
                                adapter.notifyItemChanged(requestCode);
                            });
                        },
                        error -> {
                            // Handle any errors
                            requireActivity().runOnUiThread(() -> {
                                Toast.makeText(getContext(), "Error compressing image: " + error.getMessage(), Toast.LENGTH_SHORT).show();
                            });
                        }
                );

                /*imageProcessor.compressImageFromUriAsync( getContext(), selectedImageUri, 500, compressedData -> {
                    if (compressedData != null) {
                        store.getReport().getItems().get(0).getCheckPoints().get(requestCode).setFile(compressedData);
                        //store.getReport().getItems().get(0).getCheckPoints().get(requestCode).addImageList(compressedData);
                    } else {
                        store.getReport().getItems().get(0).getCheckPoints().get(requestCode).setFile(null);
                    }
                    adapter.notifyItemChanged( requestCode );
                });*/
                //adapter.notifyItemChanged(requestCode);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public byte[] uriToByteArray(Context context, Uri uri) throws IOException {
        // Target file size in bytes (100 KB)
        int targetSizeInBytes = 100 * 1024;

        // Load the image as a Bitmap without scaling down
        Bitmap bitmap;
        try (InputStream inputStream = context.getContentResolver().openInputStream(uri)) {
            bitmap = BitmapFactory.decodeStream(inputStream);
        }

        if (bitmap == null) {
            throw new IOException("Failed to decode image from URI.");
        }

        // Compress the bitmap with an initial high quality
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        int quality = 100;
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, byteArrayOutputStream);

        // Gradually reduce quality until the image is under the target size
        while (byteArrayOutputStream.size() > targetSizeInBytes && quality > 10) {
            byteArrayOutputStream.reset(); // Clear the stream for new compression
            quality -= 5;  // Reduce quality by 5 each time
            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, byteArrayOutputStream);
        }

        return byteArrayOutputStream.toByteArray();
    }

    public void uriToByteArrayAsync(
            Context context,
            Uri uri,
            int targetSizeInKB,
            Consumer<byte[]> onSuccess,
            Consumer<Exception> onError
    ) {
        new Thread(() -> {
            try {
                int targetSizeInBytes = targetSizeInKB * 1024;

                // Load the image as a Bitmap without scaling
                Bitmap bitmap;
                try (InputStream inputStream = context.getContentResolver().openInputStream(uri)) {
                    bitmap = BitmapFactory.decodeStream(inputStream);
                }

                if (bitmap == null) {
                    throw new IOException("Failed to decode image from URI.");
                }

                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                int minQuality = 10;
                int maxQuality = 100;
                int quality = maxQuality;

                // Binary search for the best quality that meets the target size
                while (minQuality <= maxQuality) {
                    byteArrayOutputStream.reset();
                    bitmap.compress(Bitmap.CompressFormat.JPEG, quality, byteArrayOutputStream);

                    int byteSize = byteArrayOutputStream.size();
                    if (byteSize > targetSizeInBytes) {
                        maxQuality = quality - 1;
                    } else {
                        minQuality = quality + 1;
                    }
                    quality = (minQuality + maxQuality) / 2;
                }

                onSuccess.accept(byteArrayOutputStream.toByteArray());
            } catch (IOException e) {
                onError.accept(e);
            }
        }).start();
    }

    private void scrollToBottom() {
        if (adapter != null && adapter.getItemCount() > 0) {
            //recyclerView.scrollToPosition(adapter.getItemCount() - 1); // Scroll to the last item
            recyclerView.smoothScrollToPosition(adapter.getItemCount() - 1); // Smooth scroll, if desired.
        }
    }

    private void checkIsRecyclerViewIsCompletelyScrolled(RecyclerView recyclerView) {
        if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
            LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
            int lastVisibleItemPosition = layoutManager.findLastCompletelyVisibleItemPosition();
            int totalItemCount = layoutManager.getItemCount();

            if (lastVisibleItemPosition == totalItemCount - 1) {
                navController.navigate(R.id.action_secondStepFragment_to_thirdStepFragment);
            } else {
                Toast.makeText(getContext(), "Please Scroll at the bottom to continue", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void updateProfileViews() throws NullPointerException {
        SharedPreferences sharedPreferences = getActivity().getSharedPreferences("login_prefs", Context.MODE_PRIVATE);
        profileName.setText(sharedPreferences.getString("name", null));
        Glide.with(getContext())
                .load(store.getProfileImage())
                .into(profileImage);
    }
}
