package com.example.quiz.utils;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

public class BitMapUtils {

    private static final int MAX_CHAR_2_INCH = 32;

    private static void writeDWord(ByteArrayOutputStream baos, int value) {
        baos.write(value & 0xFF);
        baos.write((value >> 8) & 0xFF);
        baos.write((value >> 16) & 0xFF);
        baos.write((value >> 24) & 0xFF);
    }
    private static void writeWord(ByteArrayOutputStream baos, int value) {
        baos.write(value & 0xFF);
        baos.write((value >> 8) & 0xFF);
    }
    public static byte[] bitmapToBmp(Bitmap bitmap) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();

        // Calcul de la taille des données image (lignes alignées sur 32 bits)
        int rowSize = ((width * 3 + 3) & ~3); // 3 bytes par pixel (RGB), aligné sur 4 octets
        int imageDataSize = rowSize * height;
        int fileSize = 54 + imageDataSize; // 54 = taille entête BMP

        // Entête BITMAPFILEHEADER (14 octets)
        writeWord(baos, 0x4D42); // Signature "BM"
        writeDWord(baos, fileSize); // Taille du fichier
        writeWord(baos, 0); // Réservé
        writeWord(baos, 0); // Réservé
        writeDWord(baos, 54); // Offset des données pixel

        // Entête BITMAPINFOHEADER (40 octets)
        writeDWord(baos, 40); // Taille de l'entête
        writeDWord(baos, width); // Largeur
        writeDWord(baos, height); // Hauteur
        writeWord(baos, 1); // Nombre de plans
        writeWord(baos, 24); // Bits par pixel (RGB)
        writeDWord(baos, 0); // Compression (0 = BI_RGB)
        writeDWord(baos, imageDataSize); // Taille des données image
        writeDWord(baos, 0); // Résolution horizontale (peut être 0)
        writeDWord(baos, 0); // Résolution verticale
        writeDWord(baos, 0); // Couleurs utilisées
        writeDWord(baos, 0); // Couleurs importantes

        // Extraction des pixels (BMP stocke de bas en haut)
        byte[] pixels = new byte[imageDataSize];
        for (int y = height - 1; y >= 0; y--) {
            int rowStart = (height - 1 - y) * rowSize;
            for (int x = 0; x < width; x++) {
                int pixel = bitmap.getPixel(x, y);

                // Extraire les composantes ARGB
                int blue = pixel & 0xFF;
                int green = (pixel >> 8) & 0xFF;
                int red = (pixel >> 16) & 0xFF;
                // Alpha ignoré pour BMP 24 bits

                int pos = rowStart + x * 3;
                pixels[pos] = (byte) (blue);
                pixels[pos + 1] = (byte) (green);
                pixels[pos + 2] = (byte) (red);
            }
        }

        try {
            baos.write(pixels);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

        return baos.toByteArray();
    }

    public static Bitmap resizeToPrinterWidth(Bitmap originalBitmap, int printerWidthPx) {
        int originalWidth = originalBitmap.getWidth();
        int originalHeight = originalBitmap.getHeight();
        int newHeight = (originalHeight * printerWidthPx) / originalWidth;

        // 1. Redimensionner sans filtre (conserve les contours nets)
        Bitmap scaledBitmap = Bitmap.createScaledBitmap(originalBitmap,
                printerWidthPx,
                newHeight,
                false);

        // 2. Créer un bitmap ARGB_8888 (meilleure qualité que RGB_565)
        Bitmap result = Bitmap.createBitmap(printerWidthPx, newHeight, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(result);
        canvas.drawColor(Color.WHITE);

        // 3. Dessiner avec un Paint qui préserve les couleurs
        Paint paint = new Paint();
        paint.setAntiAlias(false);  // Pas d'anti-aliasing (évite le flou)
        canvas.drawBitmap(scaledBitmap, 0, 0, paint);

        // 4. Seuillage intelligent pour garder les détails
        for (int x = 0; x < result.getWidth(); x++) {
            for (int y = 0; y < result.getHeight(); y++) {
                int pixel = result.getPixel(x, y);
                int r = Color.red(pixel);
                int g = Color.green(pixel);
                int b = Color.blue(pixel);

                // Calculer la luminosité
                int gray = (r + g + b) / 3;

                // Seuil adaptatif : si c'est sombre, deviens noir
                if (gray < 130) {  // Seuil à 200 pour garder les gris clairs
                    result.setPixel(x, y, Color.BLACK);
                } else {
                    result.setPixel(x, y, Color.WHITE);
                }
            }
        }

        return result;
    }

    public static Bitmap generateBarcodeBitmap(String contents, int width, int height) throws WriterException {
        BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.CODE_128, width, height);
        Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                bmp.setPixel(x, y, bitMatrix.get(x, y) ? android.graphics.Color.BLACK : android.graphics.Color.WHITE);
            }
        }
        return bmp;
    }

    public static String formatLineWithNumbers(String[] numbers, String separator, int requiredHorse) {
        StringBuilder currentLine = new StringBuilder();
        StringBuilder finalOutput = new StringBuilder();
        List<String> formatted = new ArrayList<>();
        if(Arrays.stream(numbers).map(String::valueOf).collect(Collectors.toList()).contains("X")){
            if(numbers.length <= requiredHorse){
                return Arrays.stream(numbers).map(String::valueOf).collect(Collectors.joining("-")).toString();
            }
            formatted = Arrays.stream(numbers).map(String::valueOf).collect(Collectors.toList());
        }else{
            formatted = Arrays.stream(numbers).map(String::valueOf).collect(Collectors.toList());
        }

        for (String number : formatted) {
            String element = (currentLine.length() == 0 ? "":separator) + number;

            // Si l'ajout dépasse la largeur max, on termine la ligne et on recommence
            if (currentLine.length() + element.length() > MAX_CHAR_2_INCH) {
                finalOutput.append(currentLine.toString()).append("\n");
                currentLine = new StringBuilder(number);
            } else {
                currentLine.append(element);
            }
        }

        if (currentLine.length() > 0) {
            finalOutput.append(currentLine.toString());
        }

        return finalOutput.toString();
    }

    public static String formatMontant(Object nombre) {
        if (nombre == null) return "0";

        try {
            double valeur;
            if (nombre instanceof String) {
                valeur = Double.parseDouble((String) nombre);
            } else {
                valeur = ((Number) nombre).doubleValue();
            }

            // On force les espaces comme séparateurs de milliers pour la lisibilité
            DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.FRANCE);
            symbols.setGroupingSeparator(' ');

            // ###,### : Regroupe par milliers
            // .## : Garde max 2 décimales si elles existent (ex: 3178000.50 -> 3 178 000.5)
            DecimalFormat df = new DecimalFormat("###,###", symbols);

            return df.format(valeur);

        } catch (Exception e) {
            // Sécurité si la String n'est vraiment pas un nombre
            return String.valueOf(nombre);
        }
    }

}
