using FFMpegCore;
using FFMpegCore.Enums;
using Standard;
using System;
using System.IO;
using System.Threading.Tasks;
using VideoConcat.Common.Tools;
using static System.Windows.Forms.DataFormats;

namespace VideoConcat.Services.Video
{
    public class VideoProcess
    {
        /// <summary>
        /// 同步删除视频指定帧和对应音频片段
        /// </summary>
        /// <param name="inputPath">输入文件路径</param>
        /// <param name="outputPath">输出文件路径</param>
        /// <param name="frameNumber">要删除的帧编号（从1开始）</param>
        /// <returns>操作是否成功</returns>
        public static async Task<bool> RemoveFrameRandomeAsync(string inputPath, string outputPath)
        {
            if (!File.Exists(inputPath))
                return false;
            // 创建临时目录
            string tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
            try
            {
                // 1. 获取视频信息
                IMediaAnalysis mediaInfo = await FFProbe.AnalyseAsync(inputPath);
                var videoStream = mediaInfo.PrimaryVideoStream;
                if (videoStream == null)
                {
                    Console.WriteLine("没有找到视频流");
                    return false;
                }

                bool isHevc = videoStream.CodecName == "hevc";

                Directory.CreateDirectory(tempDir);

                if (isHevc)
                {
                    try
                    {

                        // 临时文件路径
                        string videoConvert = Path.Combine(tempDir, $"{Guid.NewGuid()}.mp4");

                        await FFMpegArguments.FromFileInput(inputPath)
                            .OutputToFile(videoConvert, true, opt => // 设置输出格式
                                opt.WithVideoCodec("libx264")
                            ).ProcessAsynchronously();
                        mediaInfo = await FFProbe.AnalyseAsync(videoConvert);

                        inputPath = videoConvert;
                    }
                    catch (Exception)
                    {
                        throw new Exception("转换失败！");
                    }
                }
                // 1. 获取视频信息
                mediaInfo = await FFProbe.AnalyseAsync(inputPath);
                videoStream = mediaInfo.PrimaryVideoStream;
                if (videoStream == null)
                {
                    Console.WriteLine("没有找到视频流");
                    return false;
                }
                // 视频总时长（秒）
                double totalDuration = mediaInfo.Duration.TotalSeconds;
                double frameRate = videoStream.FrameRate;
                double frameDuration = Math.Round(1.0 / frameRate, 6); // 一帧时长（秒）
                int totalFram = (int)(totalDuration * frameRate);

                // 确保视频时长足够（至少20秒）
                if (totalDuration < 20)
                {
                    LogUtils.Error($"视频时长太短（{totalDuration}秒），无法抽帧");
                    return false;
                }

                var random = new Random();
                // 随机选择要删除的帧时间点（避开开头和结尾）
                int maxFrameTime = (int)totalDuration - 5; // 确保有足够的空间
                int minFrameTime = 20; // 从20秒开始
                if (maxFrameTime <= minFrameTime)
                {
                    maxFrameTime = minFrameTime + 1;
                }
                var randomFrame = random.Next(minFrameTime, maxFrameTime);

                //return RemoveVideoFrame(inputPath, outputPath, randomFrame);


                string videoPart1 = Path.Combine(tempDir, $"{Guid.NewGuid()}.mp4");
                string videoPart2 = Path.Combine(tempDir, $"{Guid.NewGuid()}.mp4");
                
                LogUtils.Info($"开始抽帧：输入={inputPath}, 输出={outputPath}, 删除帧时间={randomFrame}秒");
                
                bool hasSubVideo1 = SubVideo(inputPath, videoPart1, 0, randomFrame - 0.016);
                if (!hasSubVideo1)
                {
                    LogUtils.Error($"裁剪第一部分视频失败：{videoPart1}");
                    return false;
                }
                
                bool hasSubVideo2 = SubVideo(inputPath, videoPart2, randomFrame, totalDuration);
                if (!hasSubVideo2)
                {
                    LogUtils.Error($"裁剪第二部分视频失败：{videoPart2}");
                    return false;
                }

                LogUtils.Info($"视频裁剪成功，开始合并：{videoPart1} + {videoPart2} -> {outputPath}");
                bool isJoinSuccess = JoinVideo(outputPath, [videoPart1, videoPart2]);
                if (!isJoinSuccess)
                {
                    LogUtils.Error($"合并视频失败：{outputPath}");
                    return false;
                }

                // 验证输出文件是否存在
                if (File.Exists(outputPath))
                {
                    LogUtils.Info($"抽帧成功：{outputPath}");
                    return true;
                }
                else
                {
                    LogUtils.Error($"抽帧失败：输出文件不存在 - {outputPath}");
                    return false;
                }

            }
            catch (Exception ex)
            {
                LogUtils.Error("抽帧失败", ex);
                Console.WriteLine($"操作失败: {ex.Message}");
                return false;
            }
            finally
            {
                // 清理临时目录
                try
                {
                    if (Directory.Exists(tempDir))
                    {
                        string[] files = Directory.GetFiles(tempDir);
                        foreach (string file in files)
                        {
                            try
                            {
                                File.Delete(file);
                            }
                            catch
                            {
                                // 忽略删除失败
                            }
                        }
                        try
                        {
                            Directory.Delete(tempDir);
                        }
                        catch
                        {
                            // 忽略删除失败
                        }
                    }
                }
                catch
                {
                    // 忽略清理错误
                }
            }
        }




        /// <summary>
        /// 通过修改视频元数据（添加注释）改变MD5
        /// </summary>
        public static bool ModifyByMetadata(string inputPath, string outputPath, string comment = "JSY")
        {
            // 添加或修改视频元数据中的注释信息
            return FFMpegArguments
                   .FromFileInput(inputPath)
                   .OutputToFile(outputPath, true, options => options
                       //.WithVideoCodec("copy")  // 直接复制视频流，不重新编码
                       //.WithAudioCodec("copy")  // 直接复制音频流
                       .CopyChannel()
                       .WithCustomArgument($"-metadata comment=\"{comment}_{Guid.NewGuid()}\"")  // 添加唯一注释
                   )
                   .ProcessSynchronously();
        }


        public static bool SubVideo(string inputPath, string outputPath, Double startSec, Double endSec)
        {
            try
            {
                // 计算时长
                double duration = endSec - startSec;
                if (duration <= 0)
                {
                    LogUtils.Error($"SubVideo失败：时长无效，开始={startSec}秒, 结束={endSec}秒");
                    return false;
                }

                LogUtils.Info($"SubVideo：输入={inputPath}, 输出={outputPath}, 开始={startSec}秒, 结束={endSec}秒, 时长={duration}秒");
                
                // 使用 -ss 和 -t 参数进行裁剪
                bool result = FFMpegArguments
                    .FromFileInput(inputPath, true, options => options
                        .Seek(TimeSpan.FromSeconds(startSec))
                        .WithCustomArgument($"-t {duration}"))  // 指定时长而不是结束时间
                    .OutputToFile(outputPath, true, options => options
                        .CopyChannel())  // 复制流，不重新编码
                    .ProcessSynchronously();
                
                // 验证输出文件是否存在
                if (result && File.Exists(outputPath))
                {
                    FileInfo fileInfo = new FileInfo(outputPath);
                    LogUtils.Info($"SubVideo成功：{outputPath}, 文件大小={fileInfo.Length / 1024 / 1024}MB");
                    return true;
                }
                else
                {
                    LogUtils.Error($"SubVideo失败：输入={inputPath}, 输出={outputPath}, 开始={startSec}秒, 结束={endSec}秒, 结果={result}, 文件存在={File.Exists(outputPath)}");
                    return false;
                }
            }
            catch (Exception ex)
            {
                LogUtils.Error($"SubVideo异常：输入={inputPath}, 输出={outputPath}", ex);
                return false;
            }
        }


        public static bool SubAudio(string inputPath, string outputPath, Double startSec, Double endSec)
        {
            return FFMpegArguments
                .FromFileInput(inputPath, true, options => options.Seek(TimeSpan.FromSeconds(startSec)).EndSeek(TimeSpan.FromSeconds(endSec)))
                .OutputToFile(outputPath, true, options => options.CopyChannel())
                .ProcessSynchronously();
        }

        public static bool JoinVideo(string outPutPath, string[] videoParts)
        {
            try
            {
                // 验证所有输入文件是否存在
                foreach (var part in videoParts)
                {
                    if (!File.Exists(part))
                    {
                        LogUtils.Error($"JoinVideo失败：输入文件不存在 - {part}");
                        return false;
                    }
                }
                
                bool result = FFMpeg.Join(outPutPath, videoParts);
                
                // 验证输出文件是否存在
                if (result && File.Exists(outPutPath))
                {
                    LogUtils.Info($"JoinVideo成功：{outPutPath}");
                    return true;
                }
                else
                {
                    LogUtils.Error($"JoinVideo失败：输出文件不存在 - {outPutPath}");
                    return false;
                }
            }
            catch (Exception ex)
            {
                LogUtils.Error($"JoinVideo异常：输出={outPutPath}", ex);
                return false;
            }
        }

        public async Task<bool> ProcessVideo(string inputPath, string outputPath, string tempDir)
        {
            // 1. 获取视频信息
            IMediaAnalysis mediaInfo = await FFProbe.AnalyseAsync(inputPath);
            var videoStream = mediaInfo.PrimaryVideoStream;
            if (videoStream == null)
            {
                Console.WriteLine("没有找到视频流");
                return false;
            }
            // 视频总时长（秒）
            var totalDuration = mediaInfo.Duration.TotalSeconds;

            // 计算帧时间参数
            double frameRate = videoStream.FrameRate;
            double frameDuration = Math.Round(1.0 / frameRate, 6); // 一帧时长（秒）

            int totalFram = (int)(totalDuration * frameRate);
            // 2. 随机生成要删除的帧的时间点（避开最后一帧，防止越界）
            var random = new Random();
            var randomFrame = random.Next(20, totalFram - 10);

            double frameTime = Math.Round((randomFrame - 1) * frameDuration, 6); // 目标帧开始时间
            double nextFrameTime = Math.Round((randomFrame + 1) * frameDuration, 6); // 下一帧开始时间
                                                                                     // 临时文件路径
            string videoPart1 = Path.Combine(tempDir, $"{Guid.NewGuid()}.mp4");
            string videoPart2 = Path.Combine(tempDir, $"{Guid.NewGuid()}.mp4");
            string audioPath = Path.Combine(tempDir, $"{Guid.NewGuid()}.aac");
            string videoNoaudioPath = Path.Combine(tempDir, $"{Guid.NewGuid()}.mp4");
            string finalyPath = Path.Combine(tempDir, $"{Guid.NewGuid()}.mp4");

            string audioPart1 = Path.Combine(tempDir, $"{Guid.NewGuid()}.aac");
            string audioPart2 = Path.Combine(tempDir, $"{Guid.NewGuid()}.aac");


            // 分离视频流（不含音频）
            await FFMpegArguments
                .FromFileInput(inputPath)
                        .OutputToFile(videoNoaudioPath, true, opt => opt.WithCustomArgument("-an -c:v copy"))
                        .ProcessAsynchronously();

            if (!File.Exists(videoNoaudioPath))
                return false;

            // 分离音频流（不含视频）（如有音频）
            if (mediaInfo.PrimaryAudioStream != null)
            {
                await FFMpegArguments
                    .FromFileInput(inputPath)
                    .OutputToFile(audioPath, true, opt => opt.WithCustomArgument("-vn -c:a copy"))
                    .ProcessAsynchronously();

                if (!File.Exists(audioPath))
                    return false;
            }


            inputPath = videoNoaudioPath;




            bool hasSubVideo1 = SubVideo(inputPath, videoPart1, 0, frameTime);
            bool hasSubVideo2 = SubVideo(inputPath, videoPart2, nextFrameTime, totalDuration);
            if (!hasSubVideo1 || !hasSubVideo2)
            {
                return false;
            }


            bool isJoinSuccess = JoinVideo(finalyPath, [videoPart1, videoPart2]);
            if (!isJoinSuccess)
            {
                return false;
            }

            return await FFMpegArguments.FromFileInput(finalyPath)
                 .AddFileInput(audioPath)
                 .OutputToFile(outputPath, true, opt =>
                     opt.WithCustomArgument("-c copy -shortest -y"))
                 .ProcessAsynchronously();
        }


        public static bool RemoveVideoFrame(string inputPath, string outputPath, int frameToRemove)
        {
            // 使用FFMpegArguments构建转换流程
            return FFMpegArguments
                 .FromFileInput(inputPath)
                 .OutputToFile(outputPath, true, options => options
                     // 使用select过滤器排除指定帧（帧序号从0开始）
                     .WithCustomArgument($"select=not(eq(n\\,{frameToRemove}))")

                // $"not(eq(n\\,{frameToRemove}))");   // 注意：在C#中需要转义反斜杠
                //// 保持其他编码参数
                .WithVideoCodec("libx264")
                .WithAudioCodec("copy") // 如果不需要处理音频，直接复制
                )
                .ProcessSynchronously();
        }
    }
}
