using FFMpegCore.Enums;
using FFMpegCore.Helpers;
using FFMpegCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VideoConcat.Common.Tools;
using System.Security.Cryptography;
using System.IO;
using VideoConcat.Models;
using static VideoConcat.Models.VideoModel;



namespace VideoConcat.Services.Video
{
    internal class VideoService : BaseService
    {
        /// <summary>
        /// 将视频文件转换为ts格式
        /// </summary>
        public static string ConvertVideos(string videoPath)
        {

            var video = FFProbe.Analyse(videoPath);

            string mediaInfo = "";

            mediaInfo += $"视频: {videoPath}";
            mediaInfo += $"时长: {video.Duration}";
            mediaInfo += $"格式: {video.Format}";
            // 视频流信息
            foreach (var videoStream in video.VideoStreams)
            {
                mediaInfo += $"视频编码: {videoStream.CodecName}, 分辨率: {videoStream.Width}x{videoStream.Height}";
            }
            // 音频流信息
            foreach (var audioStream in video.AudioStreams)
            {
                mediaInfo += $"音频编码: {audioStream.CodecName}, 采样率: {audioStream.SampleRateHz} Hz";
            }

            LogUtils.Info(mediaInfo);


            FFMpegHelper.ConversionSizeExceptionCheck(video);

            string _tempMd5Name = GetLargeFileMD5(videoPath);

            //GlobalFFOptions.Current.TemporaryFilesFolder
            var destinationPath = Path.Combine(Path.GetTempPath(), $"{_tempMd5Name}{FileExtension.Ts}");

            if (File.Exists(destinationPath))
            {
                return destinationPath;
            }

            //Directory.CreateDirectory(GlobalFFOptions.Current.TemporaryFilesFolder);
            try
            {
                FFMpeg.Convert(videoPath, destinationPath, VideoType.Ts);
            }
            catch (Exception ex)
            {

                LogUtils.Info("视频转换失败！尝试另外一种转换");
                // 创建FFmpeg参数
                try
                {
                    FFMpegArguments
                        .FromFileInput(videoPath)
                        .OutputToFile(destinationPath, true, o => o
                            .WithVideoCodec("libx264") // 设置视频编码器
                            .WithAudioCodec("aac") // 设置音频编码器
                            .WithAudioSamplingRate(44100)
                            .WithAudioBitrate(128000)
                            .WithConstantRateFactor(23) // 设置质量调整参数
                            .WithCustomArgument("-vf fps=30") // 强制指定帧率（例如 30fps）
                            .WithFastStart()
                            //.WithCustomArgument("-movflags +faststart") // 确保 moov atom 正确写入
                            //.CopyChannel()
                            //.WithBitStreamFilter(Channel.Video, Filter.H264_Mp4ToAnnexB)
                            .ForceFormat(VideoType.Ts)
                        )
                        //.NotifyOnOutput(Console.WriteLine) // 打印 FFmpeg 详细日志
                        .ProcessSynchronously(true);
                    //FFMpeg.Convert(destinationPathExecp, destinationPath, VideoType.Ts);

                }
                catch (Exception e)
                {
                    LogUtils.Error($"{videoPath} 转换失败", ex);
                    LogUtils.Error($"{videoPath} 转换再次失败", e);
                }

            }

            return destinationPath;
        }

        public static string GetLargeFileMD5(string filePath)
        {
            using var md5 = MD5.Create();
            using var stream = File.OpenRead(filePath);

            byte[] buffer = new byte[8192]; // 8KB 缓冲区
            int bytesRead;
            long totalBytesRead = 0;

            while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
            {
                md5.TransformBlock(buffer, 0, bytesRead, null, 0);
                totalBytesRead += bytesRead;
                // 可在此添加进度显示：Console.WriteLine($"已读取 {totalBytesRead / 1024 / 1024}MB");
            }

            md5.TransformFinalBlock(buffer, 0, 0);

            return BitConverter.ToString(value: md5.Hash ?? []).Replace("-", "").ToLowerInvariant();
        }


        /// <summary>
        /// 清理临时文件
        /// </summary>
        public static void Cleanup(List<string> pathList)
        {
            foreach (var path in pathList)
            {
                if (File.Exists(path))
                {
                    File.Delete(path);
                }
            }
        }

        public static void JoinVideos(List<string> combination)
        {
            VideoModel videoModel = new();

            if (Directory.Exists($"{videoModel.FolderPath}\\output") == false)
            {
                Directory.CreateDirectory($"{videoModel.FolderPath}\\output");
            }


            Random random = new();
            string _tempFileName = $"{DateTime.Now:yyyyMMddHHmmss}{random.Next(100000, 999999)}.mp4";

            string _outPutName = Path.Combine($"{videoModel.FolderPath}", "output", _tempFileName); ;



            var temporaryVideoParts = combination.Select((_videoPath) =>
            {
                string _tempMd5Name = VideoService.GetLargeFileMD5(_videoPath);
                //GlobalFFOptions.Current.TemporaryFilesFolder
                return Path.Combine(Path.GetTempPath(), $"{_tempMd5Name}{FileExtension.Ts}");
            }).ToArray();

            bool _isSuccess = false;


            try
            {
                _isSuccess = FFMpegArguments
                    .FromConcatInput(temporaryVideoParts)
                    .OutputToFile(_outPutName, true, options => options
                        .CopyChannel()
                        .WithBitStreamFilter(Channel.Audio, Filter.Aac_AdtstoAsc)
                        .WithFastStart()
                        .WithVideoCodec("copy")  // 复制视频流
                        .WithAudioCodec("aac")   // 重新编码音频
                        .WithAudioSamplingRate(44100) // 强制采样率
                        .WithCustomArgument("-movflags +faststart -analyzeduration 100M -probesize 100M")
                        )
                    .ProcessSynchronously();
            }
            catch (Exception ex1)
            {
                {
                    LogUtils.Error("拼接视频失败", ex1);
                }

                //bool _isSuccess = FFMpeg.Join(_outPutName, [.. combination]);

                videoModel.Dispatcher.Invoke(() =>
                {
                    IMediaAnalysis _mediaInfo = FFProbe.Analyse(_outPutName);
                    FileInfo fileInfo = new(_outPutName);

                    videoModel.ConcatVideos.Add(new ConcatVideo()
                    {
                        Index = videoModel.ConcatVideos.Count + 1,
                        FileName = _tempFileName,
                        Size = $"{fileInfo.Length / 1024 / 1024}MB",
                        Seconds = ((int)_mediaInfo.Duration.TotalSeconds),
                        Status = _isSuccess ? "拼接成功" : "拼接失败",
                        Progress = "100%",
                    });
                });


                if (_isSuccess && videoModel.AuditImagePath != "")
                {
                    // 使用 FFMpegCore 执行添加图片到视频的操作
                    try
                    {
                        // 配置 FFmpeg 二进制文件位置（如果 FFmpeg 不在系统路径中）
                        // GlobalFFOptions.Configure(new FFOptions { BinaryFolder = "path/to/ffmpeg/bin" });

                        string _outPutNameImg = $"{videoModel.FolderPath}\\output\\{DateTime.Now:yyyyMMddHHmmss}{random.Next(100000, 999999)}.mp4";

                        string _customArg = "-filter_complex \"[0:v][1:v] overlay=0:H-h\" ";
                        // 使用 FFMpegArguments 构建命令
                        bool _isCoverSuccess = FFMpegArguments
                           .FromFileInput(_outPutName)
                           .AddFileInput(videoModel.AuditImagePath)
                           .OutputToFile(
                            _outPutNameImg,
                           true,
                           options => options
                                    .WithCustomArgument(_customArg)// 或显式指定编码器参数
                                .WithCustomArgument("-movflags +faststart") // 确保 moov atom 正确写入
                           )
                           .ProcessSynchronously();


                        LogUtils.Info($"图片已成功添加到视频中，输出文件：{_outPutName}");
                    }
                    catch (Exception ex)
                    {
                        LogUtils.Error($"图片添加到视频中失败", ex);
                    }
                }


                LogUtils.Info($"当前视频-[${_outPutName}]： {string.Join("；", combination)}    合并成功");
            }
        }
    }
}
