package org.ta.pddserver.lotto;

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.oned.Code128Writer;
import com.google.zxing.oned.Code39Writer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

public class BarcodeUtils {

    // 条形码默认宽度
    private static final int DEFAULT_WIDTH = 300;
    // 条形码默认高度
    private static final int DEFAULT_HEIGHT = 100;
    // 条形码默认颜色（黑色）
    private static final Color DEFAULT_BAR_COLOR = Color.BLACK;
    // 条形码背景色（白色）
    private static final Color DEFAULT_BACKGROUND_COLOR = Color.WHITE;

    /**
     * 生成条形码图片（返回字节数组，支持直接输出到前端）
     *
     * @param content  条形码内容（如"123456789012"）
     * @param width    宽度
     * @param height   高度
     * @param barColor 条码颜色
     * @param bgColor  背景颜色
     * @param withText 是否在条码下方显示文本
     * @return 条形码图片字节数组（PNG格式）
     */
    public static byte[] generateBarcode(String content, int width, int height,
                                         Color barColor, Color bgColor, boolean withText, int bit) throws WriterException, IOException {
        // 1. 校验参数
        if (content == null || content.isEmpty()) {
            throw new IllegalArgumentException("条形码内容不能为空");
        }
        width = Math.max(width, DEFAULT_WIDTH);
        height = Math.max(height, DEFAULT_HEIGHT);

        // 2. 设置条形码参数（编码格式：Code128，支持数字、字母、特殊字符）
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 字符集
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); // 纠错等级
        hints.put(EncodeHintType.MARGIN, 0);

        // 3. 生成条形码矩阵
        BitMatrix bitMatrix = null;
        if (bit == 39) {
            Code39Writer writer = new Code39Writer();
            bitMatrix = writer.encode(content, BarcodeFormat.CODE_39, width, width / 3, hints);
        } else if (bit == 128) {
            Code128Writer writer = new Code128Writer();
            bitMatrix = writer.encode(content, BarcodeFormat.CODE_128, width, height, hints);
        }


        // 4. 转换为BufferedImage
        BufferedImage barcodeImage = toBufferedImage(bitMatrix, barColor, bgColor);

        // 5. 若需要显示文本，在条码下方添加内容
        if (withText) {
            barcodeImage = addTextBelowBarcode(barcodeImage, content);
        }

        // 6. 转为字节数组（PNG格式）
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(barcodeImage, "png", baos);
        return baos.toByteArray();
    }

    /**
     * 生成默认样式的条形码（简化方法）
     */
    public static byte[] generateDefaultBarcode(String content) throws WriterException, IOException {
        return generateBarcode(content, DEFAULT_WIDTH, DEFAULT_HEIGHT,
                DEFAULT_BAR_COLOR, DEFAULT_BACKGROUND_COLOR, false, 128);
    }


    /**
     * 生成默认样式的条形码（简化方法）
     */
    public static byte[] generateDefaultBarcode(String content, int width, int height) throws WriterException, IOException {
        return generateBarcode(content, width, height,
                DEFAULT_BAR_COLOR, DEFAULT_BACKGROUND_COLOR, false, 128);
    }

    /**
     * 生成39的条形码（简化方法）
     */
    public static byte[] generate39Barcode(String content, int width, int height) throws WriterException, IOException {
        return generateBarcode(content, width, height,
                DEFAULT_BAR_COLOR, Color.red, false, 39);
    }

    /**
     * 生成128条形码（简化方法）
     */
    public static byte[] generate128Barcode(String content, int width, int height) throws WriterException, IOException {
        return generateBarcode(content, width, height,
                DEFAULT_BAR_COLOR, DEFAULT_BACKGROUND_COLOR, false, 128);
    }

    /**
     * 将BitMatrix转换为BufferedImage
     */
    private static BufferedImage toBufferedImage(BitMatrix matrix, Color barColor, Color bgColor) {
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        int barRGB = barColor.getRGB();
        int bgRGB = bgColor.getRGB();

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                // 矩阵中true表示条码（前景色），false表示背景
                image.setRGB(x, y, matrix.get(x, y) ? barRGB : bgRGB);
            }
        }
        return image;
    }

    /**
     * 在条形码下方添加文本（显示条形码内容）
     */
    private static BufferedImage addTextBelowBarcode(BufferedImage barcodeImage, String text) {
        int width = barcodeImage.getWidth();
        int height = barcodeImage.getHeight();
        int textHeight = 30; // 文本区域高度

        // 创建新的图片（原高度 + 文本高度）
        BufferedImage newImage = new BufferedImage(width, height + textHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = newImage.createGraphics();

        // 1. 绘制原条形码
        g2d.drawImage(barcodeImage, 0, 0, null);

        // 2. 绘制文本背景（白色）
        g2d.setColor(DEFAULT_BACKGROUND_COLOR);
        g2d.fillRect(0, height, width, textHeight);

        // 3. 绘制文本（居中）
        g2d.setColor(DEFAULT_BAR_COLOR);
        g2d.setFont(new Font("Arial", Font.PLAIN, 16)); // 文本字体
        FontMetrics metrics = g2d.getFontMetrics();
        int textX = (width - metrics.stringWidth(text)) / 2; // 水平居中
        int textY = height + textHeight - 5; // 垂直位置（距离底部5px）
        g2d.drawString(text, textX, textY);

        g2d.dispose();
        return newImage;
    }

    /**
     * 解析条形码图片，获取内容
     *
     * @param imagePath 图片路径
     * @return 条形码内容
     */
    public static String parseBarcode(String imagePath) throws IOException, NotFoundException {
        BufferedImage image = ImageIO.read(new File(imagePath));
        LuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

        // 设置解析参数
        Map<DecodeHintType, Object> hints = new HashMap<>();
        hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");

        // 解析条形码
        Result result = new MultiFormatReader().decode(bitmap, hints);
        return result.getText();
    }

    /**
     * 解析条形码字节数组（适用于网络传输的图片）
     */
    public static String parseBarcode(byte[] imageBytes) throws IOException, NotFoundException {
        BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageBytes));
        LuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

        Map<DecodeHintType, Object> hints = new HashMap<>();
        hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");

        Result result = new MultiFormatReader().decode(bitmap, hints);
        return result.getText();
    }
}