package com.m2sdl.undercooked;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;

import com.m2sdl.undercooked.domain.Review;
import com.m2sdl.undercooked.services.FirebaseBackendService;
import com.m2sdl.undercooked.services.UndercookedService;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ReviewActivity extends AppCompatActivity {
    private final List<File> photoFiles = new ArrayList<>();
    private final FirebaseBackendService db = new FirebaseBackendService();
    private EditText reviewText;
    private Button confirmButton;
    private FrameLayout loadingOverlay;
    private LinearLayout photoContainer;
    private Button buttonTakePhoto;
    private ActivityResultLauncher<Intent> cameraLauncher;
    private UndercookedService service;
    private double latitude;
    private double longitude;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_review);

        latitude = getIntent().getDoubleExtra("lat", 0);
        longitude = getIntent().getDoubleExtra("lon", 0);

        initialSetup();
        setupConfirmButton();
    }

    private void initialSetup() {
        reviewText = findViewById(R.id.review);
        confirmButton = findViewById(R.id.confirmReview);
        photoContainer = findViewById(R.id.photoContainer);
        buttonTakePhoto = findViewById(R.id.buttonTakePhoto);
        loadingOverlay = findViewById(R.id.loadingOverlay);

        cameraLauncher = registerForActivityResult(
                new ActivityResultContracts.StartActivityForResult(),
                result -> {
                    if (result.getResultCode() == RESULT_OK && result.getData() != null) {
                        String path = result.getData().getStringExtra("photoUri");
                        if (path != null) {
                            File file = new File(path);
                            photoFiles.add(file);
                            updatePhotoViews();
                        }
                    }
                }
        );

        buttonTakePhoto.setOnClickListener(v -> {
            Intent intent = new Intent(this, CameraActivity.class);
            cameraLauncher.launch(intent);
        });

        service = new UndercookedService();
    }

    private void setupConfirmButton() {
        confirmButton.setOnClickListener(v -> {
            String text = reviewText.getText().toString().trim();

            if (text.isEmpty()) {
                Toast.makeText(this, "Veuillez écrire un avis.", Toast.LENGTH_SHORT).show();
                return;
            }

            showLoading();
            uploadImagesAndSaveReview(text);
        });
    }

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

        if (requestCode == 1001 && resultCode == RESULT_OK) {
            String path = data.getStringExtra("photoUri");
            if (path != null) {
                File file = new File(path);
                photoFiles.add(file);
                updatePhotoViews();
            }
        }
    }


    private void updatePhotoViews() {
        photoContainer.removeAllViews();
        for (int i = 0; i < photoFiles.size(); i++) {
            File file = photoFiles.get(i);

            FrameLayout frame = new FrameLayout(this);
            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(240, 240);
            lp.setMargins(8, 8, 8, 8);
            frame.setLayoutParams(lp);

            ImageView imageView = new ImageView(this);
            imageView.setImageURI(Uri.fromFile(file));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            frame.addView(imageView, new FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.MATCH_PARENT,
                    FrameLayout.LayoutParams.MATCH_PARENT));

            ImageButton deleteButton = new ImageButton(this);
            deleteButton.setImageResource(android.R.drawable.ic_menu_close_clear_cancel);
            deleteButton.setBackgroundColor(android.graphics.Color.TRANSPARENT);
            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(60, 60);
            params.gravity = android.view.Gravity.TOP | android.view.Gravity.END;
            deleteButton.setLayoutParams(params);
            deleteButton.setOnClickListener(v -> {
                photoFiles.remove(file);
                updatePhotoViews();
            });
            frame.addView(deleteButton);

            photoContainer.addView(frame);
        }
    }

    private File compressImage(File original) throws IOException {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(original.getAbsolutePath(), options);

        int maxSize = 1280;
        int scale = 1;
        while (options.outWidth / scale > maxSize || options.outHeight / scale > maxSize) {
            scale *= 2;
        }

        BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
        decodeOptions.inSampleSize = scale;

        Bitmap bitmap = BitmapFactory.decodeFile(original.getAbsolutePath(), decodeOptions);

        File compressedFile = new File(getCacheDir(), original.getName());

        FileOutputStream out = new FileOutputStream(compressedFile);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
        out.flush();
        out.close();

        bitmap.recycle();

        return compressedFile;
    }

    private void uploadImagesAndSaveReview(String text) {
        List<String> uploadedUrls = new ArrayList<>();

        if (photoFiles.isEmpty()) {
            saveReview(text, uploadedUrls, () -> {
                runOnUiThread(() -> {
                    hideLoading();
                    Toast.makeText(ReviewActivity.this, "Avis envoyé !", Toast.LENGTH_SHORT).show();
                    finish();
                });
            });
            return;
        }

        UndercookedService.OnImageUploaded callback = new UndercookedService.OnImageUploaded() {
            @Override
            public void onUploaded(String url) {
                uploadedUrls.add(url);

                if (uploadedUrls.size() == photoFiles.size()) {
                    runOnUiThread(() -> {
                        saveReview(text, uploadedUrls, () -> {
                            hideLoading();
                            Toast.makeText(ReviewActivity.this, "Avis envoyé !", Toast.LENGTH_SHORT).show();
                            finish();
                        });
                    });
                }
            }

            @Override
            public void onError(Exception e) {
                runOnUiThread(() -> {
                    hideLoading();
                    Toast.makeText(
                            ReviewActivity.this,
                            "Erreur upload image",
                            Toast.LENGTH_SHORT
                    ).show();
                });
            }
        };

        for (File file : photoFiles) {
            File compressed;
            try {
                compressed = compressImage(file);
            } catch (IOException e) {
                Toast.makeText(this, "Erreur compression image", Toast.LENGTH_SHORT).show();
                return;
            }

            service.uploadImageToServer(compressed, callback);
        }
    }


    private void saveReview(String text, List<String> imageUrls, Runnable onSaved) {
        Review review = new Review(text, imageUrls, latitude, longitude);

        db.addReview(review).addOnSuccessListener(docRef -> onSaved.run());
    }

    private void showLoading() {
        loadingOverlay.setVisibility(FrameLayout.VISIBLE);
        confirmButton.setEnabled(false);
        buttonTakePhoto.setEnabled(false);
    }

    private void hideLoading() {
        loadingOverlay.setVisibility(FrameLayout.GONE);
        confirmButton.setEnabled(true);
        buttonTakePhoto.setEnabled(true);
    }
}
