package com.utopiaindustries.qualitychecker.utils;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;

import androidx.appcompat.app.AlertDialog;
import androidx.core.content.FileProvider;

import com.utopiaindustries.qualitychecker.R;
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 java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.Objects;
import java.util.function.Consumer;

public class FileUtils {
    public static String writeFile( Context context ,
                                      byte[] content,
                                      String fileName ){
        FileOutputStream fos = null;
        try {
            // Get the file path in the internal storage
            File file = new File( context.getFilesDir(), fileName);
            // Open the file output stream
            fos = new FileOutputStream(file);
            fos.write( content );
            fos.flush();
           return file.getAbsolutePath();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return "";
    }

    public static byte[] readFile(String filePath) throws IOException {
        File file = new File(filePath);
        try (FileInputStream fis = new FileInputStream(file);
             ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                baos.write(buffer, 0, bytesRead);
            }
            return baos.toByteArray();
        }
    }

    public static void deleteFile(String filePath) {
        File file = new File(filePath);
        if (file.exists()) {
            if (file.delete()) {
                System.out.println("File deleted successfully");
            } else {
                System.out.println("Failed to delete the file");
            }
        } else {
            System.out.println("File does not exist");
        }
    }

    public static Uri getImageUriFromBitmap(Context context, Bitmap bitmap) {
        // Create a file in the cache directory
        File cachePath = new File(context.getCacheDir(), "images");
        cachePath.mkdirs(); // Create the directory if it doesn't exist
        File file = new File(cachePath, "image.png"); // File name with PNG format

        try {
            // Write the bitmap to the file
            FileOutputStream stream = new FileOutputStream(file);
            //bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); // 100 indicates no compression
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
            stream.flush();
            stream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Get the URI using FileProvider
        Uri uri = FileProvider.getUriForFile(context, "com.utopiaindustries.qualitychecker.fileprovider", file);

        return uri;
    }

    private void  saveDraftReportDialog(Context context, InspectionReportService inspectionReportService, Store store) {
        LayoutInflater inflater = LayoutInflater.from(context );
        View dialogView = inflater.inflate( R.layout.save_report_dialog, null);
        // progress bar
        ProgressBar progressBar = dialogView.findViewById( R.id.save_report_progress );

        AlertDialog.Builder builder = new AlertDialog.Builder( Objects.requireNonNull(context) );
        builder.setView( dialogView )
                .setTitle("So you want to save report as draft?")
                .setPositiveButton( "Save",(dialog, which) -> {
                    progressBar.setVisibility(View.VISIBLE);
                    NotificationHelper.showNotification(Objects.requireNonNull(context),
                            "Utopia QA App",
                            "Report is saving keep patience...");
                    inspectionReportService.saveInLocalDb(context, store.getReport(), new SaveReportCallback() {
                        @Override
                        public void onSuccess() {
                            Handler handler = new Handler(Looper.getMainLooper());
                            handler.post(() -> {
                                Toast.makeText(context, "Report draft Successfully", Toast.LENGTH_LONG).show();
                                progressBar.setVisibility(View.INVISIBLE);
                                //Objects.requireNonNull(context).finish();
                                NotificationHelper.showNotification(Objects.requireNonNull(context),
                                        "Utopia QA App",
                                        "Report is successfully saved");
                            });
                        }

                        @Override
                        public void onFailure(Throwable throwable) {
                            Handler handler = new Handler(Looper.getMainLooper());
                            handler.post(() -> {
                                Toast.makeText(context, throwable.getMessage(), Toast.LENGTH_LONG).show();
                                progressBar.setVisibility(View.INVISIBLE);
                                NotificationHelper.showNotification(Objects.requireNonNull(context),
                                        "Utopia QA App",
                                        "Error in saving report");
                            });
                        }
                    });
                })
                .setNegativeButton("Cancel", (dialog, which) -> {
                    // Handle Cancel button click
                    dialog.dismiss();
                });
        // Show the dialog
        AlertDialog dialog = builder.create();
        progressBar.setVisibility( View.GONE );
        dialog.show();

    }

    public static void convertUriToByteArrayAsync(
            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();
    }

    public static byte[] readFileToByteArray(String path) throws IOException {
        File file = new File(path);
        FileInputStream fis = new FileInputStream(file);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = fis.read(buffer)) != -1) {
            bos.write(buffer, 0, bytesRead);
        }
        fis.close();
        return bos.toByteArray();
    }


    /**
     * is null or empty
     */
    public static boolean isNullOrEmpty( String str ) {
        return str == null || str.isEmpty();
    }

    public static boolean isNetworkConnected(Context context) {
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
        return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
    }

    public static boolean copyFile(Context context, String sourcePath, String destFileName) {
        try {
            // Read bytes from source file
            byte[] fileBytes = readFile(sourcePath);

            // Write bytes to new file in external files directory
            File destFile = new File(context.getExternalFilesDir(null), destFileName);
            try (FileOutputStream fos = new FileOutputStream(destFile)) {
                fos.write(fileBytes);
                fos.flush();
            }

            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    public static void exportFileToExternalStorage(final Context context, String internalFileName) {
        try {
            // Source: internal storage file
            File internalFile = new File(context.getFilesDir(), internalFileName);

            // Destination: external storage file
            File externalFile = new File(context.getExternalFilesDir(null), internalFileName);

            FileInputStream fis = new FileInputStream(internalFile);
            FileOutputStream fos = new FileOutputStream(externalFile);

            byte[] buffer = new byte[1024];
            int length;
            while ((length = fis.read(buffer)) > 0) {
                fos.write(buffer, 0, length);
            }

            fis.close();
            fos.close();

            //Toast.makeText(this, "Exported to: " + externalFile.getAbsolutePath(), Toast.LENGTH_LONG).show();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static Object readSerializedObject(String filePath) {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath))) {
            return ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void writeObjectToReadableFile(Context context, Object obj, String outputFileName) {
        File outputFile = new File(context.getExternalFilesDir(null), outputFileName);
        try (FileWriter writer = new FileWriter(outputFile)) {
            writer.write(obj.toString()); // You can also use a JSON library here if needed
            writer.flush();
            Log.e("FileUtils", "Object written to: " + outputFile.getAbsolutePath());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
