package com.yaoai.media.service;

import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
public class FfmpegService {

    @Value("${ffmpeg.path:ffmpeg}")
    private String ffmpegPath;

    @Value("${ffmpeg.work-dir:}")
    private String workDirConfig;

    private String workDir;

    @PostConstruct
    void init() {
        workDir = workDirConfig == null || workDirConfig.isBlank()
                ? System.getProperty("java.io.tmpdir") + "/yaoai-ffmpeg"
                : workDirConfig;
        log.info("FfmpegService initialized: ffmpeg={}, workDir={}", ffmpegPath, workDir);
    }

    private final HttpClient http = HttpClient.newBuilder()
            .followRedirects(HttpClient.Redirect.NORMAL)
            .build();

    /**
     * 下载多个视频 URL，用 ffmpeg concat 拼接成一个 MP4，返回本地输出文件路径。
     * 调用方负责删除临时文件。
     */
    public Path concatVideos(List<String> videoUrls) throws IOException, InterruptedException {
        if (videoUrls == null || videoUrls.isEmpty()) {
            throw new IllegalArgumentException("videoUrls 不能为空");
        }

        String jobId = UUID.randomUUID().toString().replace("-", "").substring(0, 12);
        Path jobDir = Path.of(workDir, jobId);
        Files.createDirectories(jobDir);
        log.info("FFmpeg job {} starting, {} clips", jobId, videoUrls.size());

        List<Path> clips = new ArrayList<>();
        for (int i = 0; i < videoUrls.size(); i++) {
            Path clipPath = jobDir.resolve("clip_" + i + ".mp4");
            downloadTo(videoUrls.get(i), clipPath);
            clips.add(clipPath);
        }

        Path concatList = jobDir.resolve("concat.txt");
        List<String> lines = new ArrayList<>();
        for (Path clip : clips) {
            lines.add("file '" + clip.toAbsolutePath().toString().replace("\\", "/") + "'");
        }
        Files.write(concatList, lines, StandardCharsets.UTF_8);

        Path output = jobDir.resolve("output.mp4");
        List<String> cmd = List.of(
                ffmpegPath,
                "-f", "concat",
                "-safe", "0",
                "-i", concatList.toAbsolutePath().toString(),
                "-c", "copy",
                "-y",
                output.toAbsolutePath().toString()
        );

        log.info("Running FFmpeg: {}", String.join(" ", cmd));
        ProcessBuilder pb = new ProcessBuilder(cmd);
        pb.redirectErrorStream(true);
        pb.redirectOutput(jobDir.resolve("ffmpeg.log").toFile());
        Process proc = pb.start();
        int exit = proc.waitFor();

        if (exit != 0) {
            String ffmpegLog = Files.readString(jobDir.resolve("ffmpeg.log"), StandardCharsets.UTF_8);
            log.error("FFmpeg exit={}, log:\n{}", exit, ffmpegLog);
            throw new IOException("FFmpeg 失败，exit=" + exit);
        }

        log.info("FFmpeg job {} done, output={}", jobId, output);
        return output;
    }

    /** 清理整个 job 目录（调用方在上传完结果后调用） */
    public void cleanup(Path outputFile) {
        try {
            Path jobDir = outputFile.getParent();
            if (jobDir != null) {
                try (var stream = Files.walk(jobDir)) {
                    stream.sorted((a, b) -> -a.compareTo(b)).forEach(p -> {
                        try { Files.deleteIfExists(p); } catch (IOException ignored) {}
                    });
                }
            }
        } catch (Exception e) {
            log.warn("FFmpeg cleanup failed: {}", e.getMessage());
        }
    }

    private void downloadTo(String url, Path dest) throws IOException, InterruptedException {
        HttpRequest req = HttpRequest.newBuilder(URI.create(url))
                .GET()
                .header("User-Agent", "YaoAI-Studio/1.0")
                .build();
        HttpResponse<Path> resp = http.send(req, HttpResponse.BodyHandlers.ofFile(dest));
        if (resp.statusCode() >= 400) {
            throw new IOException("下载视频失败 HTTP " + resp.statusCode() + ": " + url);
        }
        log.debug("Downloaded {} -> {} ({} bytes)", url, dest, Files.size(dest));
    }
}
