package cn.bunny.video;

import cn.bunny.video.dao.Response;
import cn.bunny.video.dao.VideoEntity;
import cn.bunny.video.utils.HttpRequestUtils;
import cn.bunny.video.utils.SystemControlUtils;
import io.micrometer.common.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class VideoDownloadVersion2 {
    private static final Logger log = LoggerFactory.getLogger(VideoDownloadVersion2.class);

    // 当前下载页
    private static final Integer currentPage = 7;

    // 线程池个数
    private static final Integer threadPoolSize = 10;

    // 下载目录
    private static final String DOWNLOAD_DIR = "G:\\video\\";

    // 视频下载URL基础部分
    private static final String BASE_URL = "https://mjfh136.cyou/view/videoList/1637462276570050562/";

    // 开始线程池
    private static final ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);

    public static void main(String[] args) {
        Instant start = Instant.now();
        try {
            String url = BASE_URL + currentPage + "/80";
            HttpRequestUtils<Response<VideoEntity>> requestUtils = new HttpRequestUtils<>();
            Response<VideoEntity> responseData = requestUtils.requestGET(url);

            // 接收到返回信息
            downloadVideoList(responseData);

            // 执行完成后播放音乐
            shutdownExecutorService();

            // 计算程序运行时间
            Instant end = Instant.now();
            Duration duration = Duration.between(start, end);
            long minutes = duration.toMinutes();
            long seconds = duration.minusMinutes(minutes).getSeconds();
            log.info("程序运行时间：{} 分钟 {} 秒", minutes, seconds);

        } catch (Exception exception) {
            log.error("下载过程中发生异常", exception);
        }
    }

    /**
     * 下载视频列表内容
     *
     * @param responseData 返回一页的数据响应
     */
    private static void downloadVideoList(Response<VideoEntity> responseData) {
        List<VideoEntity> videoEntities = responseData.getData().getList();

        // 使用并行流代替传统的流操作，并且进行命令的预构建
        videoEntities.parallelStream()
                .filter(videoEntity -> videoEntity.getPlayUrl().contains("http"))
                .peek(videoEntity -> {
                    if (StringUtils.isBlank(videoEntity.getVideoTag())) {
                        videoEntity.setVideoTag(videoEntity.getVideoTypeTitle());
                    }
                })
                .forEach(videoEntity -> {
                    executorService.submit(() -> {
                        try {
                            String videoTitle = videoEntity.getTitle().trim();
                            String videoUrl = videoEntity.getPlayUrl();

                            log.info("开始下载视频：{}，URL：{}", videoTitle, videoUrl);

                            List<String> command = buildDownloadCommand(videoEntity);

                            // 开始下载
                            SystemControlUtils.startProcess(command);
                        } catch (Exception e) {
                            log.error("下载视频失败，视频标题: {}", videoEntity.getTitle(), e);
                        }
                    });
                });
    }

    /**
     * 构建下载命令
     *
     * @param videoEntity 视频实体
     * @return 命令列表
     */
    private static List<String> buildDownloadCommand(VideoEntity videoEntity) {
        List<String> command = new ArrayList<>();
        command.add("N_m3u8DL-CLI");
        command.add("\"" + videoEntity.getPlayUrl() + "\"");
        command.add("--workDir");
        command.add("\"" + DOWNLOAD_DIR + videoEntity.getVideoTag() + "\"");
        command.add("--saveName");
        command.add("\"" + videoEntity.getTitle().trim() + "\"");
        command.add("--enableDelAfterDone");
        command.add("--enableBinaryMerge");
        command.add("--enableMuxFastStart");

        return command;
    }

    /**
     * 优雅地关闭线程池
     */
    private static void shutdownExecutorService() {
        try {
            executorService.shutdown();
            if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                executorService.shutdownNow();
            }
            SystemControlUtils.playMusic();
        } catch (InterruptedException e) {
            executorService.shutdownNow();
            Thread.currentThread().interrupt();
            log.error("线程池等待超时，强制关闭线程池", e);
        }
    }
}