package com.fuyuanshen.demo.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import com.fuyuanshen.common.core.domain.R;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.file.Files;
import java.util.Base64;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameUtils;
import org.springframework.http.ResponseEntity;

@RestController
@RequestMapping("/video")
public class VideoUploadController {

    // 可配置项：建议从 application.yml 中读取
    private static final int MAX_VIDEO_SIZE = 10 * 1024 * 1024; // 10 MB
    private static final int FRAME_RATE = 15; // 每秒抽15帧
    private static final int DURATION = 2; // 抽2秒
    private static final int TOTAL_FRAMES = FRAME_RATE * DURATION;
    private static final int WIDTH = 160;
    private static final int HEIGHT = 80;
    private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();

    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public R<List<String>> upload(@RequestParam("file") MultipartFile file) {
        if (file == null || file.isEmpty()) {
            return R.fail("上传文件不能为空");
        }

        if (!isVideo(file.getOriginalFilename())) {
            return R.fail("只允许上传视频文件");
        }

        if (file.getSize() > MAX_VIDEO_SIZE) {
            return R.fail("视频大小不能超过10MB");
        }

        File tempFile = null;
        try {
            // 创建临时文件保存上传的视频
            tempFile = createTempVideoFile(file);


            List<BufferedImage> frames = extractFramesFromVideo(tempFile);
            if (frames.isEmpty()) {
                return R.fail("无法提取任何帧");
            }

            // ✅ 新增：保存帧为图片
            //saveFramesToLocal(frames, "extracted_frame");

            byte[] binaryData = convertFramesToRGB565(frames);
//            String base64Data = Base64.getEncoder().encodeToString(binaryData);
//
//            return R.ok(base64Data);
            // 构造响应头
            // 将二进制数据转为 Hex 字符串
            // 转换为 Hex 字符串列表
            List<String> hexList = bytesToHexList(binaryData);

            return R.ok(hexList);

        } catch (Exception e) {
            return R.fail("视频处理失败：" + e.getMessage());
        } finally {
            deleteTempFile(tempFile);
        }
    }

    /**
     * rgb565 转 hex
     */
    private List<String> bytesToHexList(byte[] bytes) {
        List<String> hexList = new ArrayList<>();
        for (byte b : bytes) {
            int value = b & 0xFF;
            char high = HEX_ARRAY[value >>> 4];
            char low = HEX_ARRAY[value & 0x0F];
            hexList.add(String.valueOf(high) + low);
        }
        return hexList;
    }

    /**
     * 创建临时文件并保存上传的视频
     */
    private File createTempVideoFile(MultipartFile file) throws Exception {
        File tempFile = Files.createTempFile("upload-", ".mp4").toFile();
        file.transferTo(tempFile);
        return tempFile;
    }

    /**
     * 从视频中按时间均匀提取指定数量的帧
     */
    private List<BufferedImage> extractFramesFromVideo(File videoFile) throws Exception {
        List<BufferedImage> frames = new ArrayList<>();

        try (FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(videoFile)) {
            grabber.start();

            // 获取视频总帧数和帧率
            long totalFramesInVideo = grabber.getLengthInFrames();
            int fps = (int) Math.round(grabber.getFrameRate());
            if (fps <= 0) fps = 30;

            double durationSeconds = (double) totalFramesInVideo / fps;

            if (durationSeconds < DURATION) {
                throw new IllegalArgumentException("视频太短，至少需要 " + DURATION + " 秒");
            }

            // 计算每帧之间的间隔（浮点以实现更精确跳转）
            double frameInterval = (double) totalFramesInVideo / TOTAL_FRAMES;

            for (int i = 0; i < TOTAL_FRAMES; i++) {
                int targetFrameNumber = (int) Math.round(i * frameInterval);

                // 避免设置无效帧号
                if (targetFrameNumber >= totalFramesInVideo) {
                    throw new IllegalArgumentException("目标帧超出范围: " + targetFrameNumber + " ");
                }

                grabber.setFrameNumber(targetFrameNumber);
                Frame frame = grabber.grab();

                if (frame != null && frame.image != null) {
                    BufferedImage bufferedImage = Java2DFrameUtils.toBufferedImage(frame);
                    frames.add(cropImage(bufferedImage, WIDTH, HEIGHT));
                } else {
                    throw new IllegalArgumentException("无法获取第 " + targetFrameNumber + "帧 ");
                }
            }

            grabber.stop();
        }

        return frames;
    }

    /**
     * 将抽取的帧保存到本地，用于调试
     */
    private void saveFramesToLocal(List<BufferedImage> frames, String prefix) {
        // 指定输出目录
        File outputDir = new File("output_frames");
        if (!outputDir.exists()) {
            outputDir.mkdirs();
        }

        int index = 0;
        for (BufferedImage frame : frames) {
            try {
                File outputImage = new File(outputDir, prefix + "_" + (index++) + ".png");
                ImageIO.write(frame, "png", outputImage);
                System.out.println("保存帧图片成功: " + outputImage.getAbsolutePath());
            } catch (Exception e) {
                throw new IllegalArgumentException("保存帧图片失败 " + e);
            }
        }
    }

    /**
     * 将所有帧转换为 RGB565 格式字节数组
     */
    private byte[] convertFramesToRGB565(List<BufferedImage> frames) throws Exception {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

        for (BufferedImage image : frames) {
            byte[] rgb565Bytes = convertToRGB565(image);
            byteArrayOutputStream.write(rgb565Bytes);
        }

        return byteArrayOutputStream.toByteArray();
    }

    /**
     * 判断是否是支持的视频格式
     */
    private boolean isVideo(String filename) {
        String ext = filename.substring(filename.lastIndexOf('.')).toLowerCase();
        return Arrays.asList(".mp4", ".avi", ".mov", ".mkv").contains(ext);
    }

    /**
     * 裁剪图像到目标尺寸
     */
    private BufferedImage cropImage(BufferedImage img, int targetWidth, int targetHeight) {
        int w = Math.min(img.getWidth(), targetWidth);
        int h = Math.min(img.getHeight(), targetHeight);
        return img.getSubimage(0, 0, w, h);
    }

    /**
     * 将 BufferedImage 转换为 RGB565 格式的字节数组
     */
    private byte[] convertToRGB565(BufferedImage image) {
        int width = image.getWidth();
        int height = image.getHeight();
        byte[] result = new byte[width * height * 2]; // RGB565: 2 bytes per pixel
        int index = 0;

        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int rgb = image.getRGB(x, y);
                int r = ((rgb >> 16) & 0xFF) >> 3;
                int g = ((rgb >> 8) & 0xFF) >> 2;
                int b = (rgb & 0xFF) >> 3;
                short pixel = (short) ((r << 11) | (g << 5) | b);

                result[index++] = (byte) (pixel >> 8); // High byte first
                result[index++] = (byte) pixel;
            }
        }

        return result;
    }

    /**
     * 删除临时文件
     */
    private void deleteTempFile(File file) {
        if (file != null && file.exists()) {
            if (!file.delete()) {
                throw new IllegalArgumentException("无法删除临时文件:  " + file.getAbsolutePath());
            }
        }
    }
}