using FFMpegCore;
using FFMpegCore.Enums;
using Microsoft.Expression.Drawing.Core;
using System.IO;
using System.Threading;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Threading;
using VideoConcat.Common.Tools;
using VideoConcat.Models;
using VideoConcat.Services.Video;
using static VideoConcat.Models.VideoModel;
using MessageBox = System.Windows.MessageBox;

namespace VideoConcat.ViewModels
{
    public class ExtractWindowViewModel
    {
        private ExtractWindowModel _extractWindowModel;

        public List<ConcatVideo> ConcatVideos { get; set; } = [];

        public ExtractWindowModel ExtractWindowModel
        {
            get { return _extractWindowModel; }
            set
            {
                _extractWindowModel = value;
            }
        }



        public ExtractWindowViewModel()
        {
            ExtractWindowModel = new ExtractWindowModel
            {
                CanExtractFrame = false,
                CanModify = false,
                IsStart = false,
                IsCanOperate = true,

                BtnOpenFolderCommand = new Command()
                {
                    DoExcue = obj =>
                    {
                        System.Windows.Forms.FolderBrowserDialog folderBrowserDialog = new();
                        if (folderBrowserDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                        {
                            ExtractWindowModel.FolderPath = folderBrowserDialog.SelectedPath;
                            LogUtils.Info($"获取视频文件夹,视频路径:{ExtractWindowModel.FolderPath}");
                            ListFolder();
                        }
                    }

                },

                BtnStartVideoConcatCommand = new Command()
                {
                    DoExcue = obj =>
                    {
                        // 在后台任务中执行异步操作
                        Task.Run(async () =>
                        {
                            int extractCount = ExtractWindowModel.ExtractCount;
                            if (extractCount <= 0)
                            {
                                ExtractWindowModel.Dispatcher.Invoke(() =>
                                {
                                    MessageBox.Show("请输入有效的生成个数（大于0）！", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                                });
                                return;
                            }

                            string modeText = ExtractWindowModel.ExtractFrameMode == Models.ExtractFrameMode.DeleteFrame ? "方案1" : "方案2";
                            DateTime startTime = DateTime.Now;
                            
                            ExtractWindowModel.Dispatcher.Invoke(() =>
                            {
                                ExtractWindowModel.HelpInfo = $"处理方案：{modeText} | 视频数量：{ExtractWindowModel.videos.Length} 个 | 每个生成：{extractCount} 个 | 总任务数：{ExtractWindowModel.videos.Length * extractCount} 个 | 开始时间：{startTime:yyyy-MM-dd HH:mm:ss}";
                                // 清空任务列表，以便重新开始
                                ExtractWindowModel.TaskItems.Clear();
                                ExtractWindowModel.IsStart = true;
                                ExtractWindowModel.IsCanOperate = false;
                            });

                            SemaphoreSlim semaphore = new(10); // 限制并发数量

                            List<Task> _tasks = [];
                            int totalTasks = ExtractWindowModel.videos.Length * extractCount;
                            int completedTasks = 0;
                            System.Collections.Concurrent.ConcurrentBag<string> errorMessages = new(); // 收集错误信息
                            System.Collections.Concurrent.ConcurrentBag<string> successMessages = new(); // 收集成功信息
                            long totalOriginalSize = 0; // 原始文件总大小
                            long totalOutputSize = 0; // 输出文件总大小
                            int successCount = 0; // 成功数量
                            int skipCount = 0; // 跳过数量（已存在）

                            // 对每个视频生成指定数量的抽帧视频
                            foreach (var video in ExtractWindowModel.videos)
                            {
                                for (int i = 1; i <= extractCount; i++)
                                {
                                    int currentIndex = i; // 闭包变量
                                    string currentVideo = video; // 闭包变量
                                    
                                    await semaphore.WaitAsync();
                                    var _task = Task.Run(async () =>
                                    {
                                        try
                                        {
                                            string _tmpPath = Path.GetDirectoryName(currentVideo) ?? "";
                                            if (string.IsNullOrEmpty(_tmpPath))
                                            {
                                                LogUtils.Error($"无法获取视频目录：{currentVideo}");
                                                Interlocked.Increment(ref completedTasks);
                                                ExtractWindowModel.Dispatcher.Invoke(() =>
                                                {
                                                    ExtractWindowModel.HelpInfo = $"处理中... ({completedTasks}/{totalTasks})";
                                                });
                                                return;
                                            }

                                            string originalFileName = Path.GetFileNameWithoutExtension(currentVideo);
                                            string extension = Path.GetExtension(currentVideo);
                                            
                                            // 生成唯一的文件名：原始名称+方案号+生成日期+序号
                                            string modeSuffix = ExtractWindowModel.ExtractFrameMode == Models.ExtractFrameMode.DeleteFrame ? "方案1" : "方案2";
                                            string dateStr = DateTime.Now.ToString("yyyyMMdd");
                                            string _tmpFileName = $"{originalFileName}_{modeSuffix}_{dateStr}_{currentIndex:D4}{extension}";

                                            string outPath = Path.Combine(_tmpPath, "out");
                                            LogUtils.Info($"准备创建输出目录：{outPath}");
                                            
                                            try
                                            {
                                                if (!Directory.Exists(outPath))
                                                {
                                                    Directory.CreateDirectory(outPath);
                                                    LogUtils.Info($"已创建输出目录：{outPath}");
                                                }
                                            }
                                            catch (Exception ex)
                                            {
                                                LogUtils.Error($"创建输出目录失败：{outPath}", ex);
                                                Interlocked.Increment(ref completedTasks);
                                                ExtractWindowModel.Dispatcher.Invoke(() =>
                                                {
                                                    ExtractWindowModel.HelpInfo = $"处理中... ({completedTasks}/{totalTasks})";
                                                });
                                                return;
                                            }

                                            string outputPath = Path.Combine(outPath, _tmpFileName);
                                            LogUtils.Info($"开始抽帧：输入={currentVideo}, 输出={outputPath}");
                                            
                                            // 定义显示用的变量（提前定义，避免作用域问题）
                                            // 显示完整的文件名，让DataGrid的列宽和ToolTip来处理显示
                                            string displayFileName = originalFileName;
                                            int currentCompleted;
                                            double progressPercent;
                                            
                                            // 获取原始文件大小
                                            long originalSize = 0;
                                            if (File.Exists(currentVideo))
                                            {
                                                FileInfo originalFileInfo = new FileInfo(currentVideo);
                                                originalSize = originalFileInfo.Length;
                                                Interlocked.Add(ref totalOriginalSize, originalSize);
                                            }
                                            
                                            // 如果文件已存在，跳过（不覆盖）
                                            if (File.Exists(outputPath))
                                            {
                                                LogUtils.Info($"文件已存在，跳过：{outputPath}");
                                                Interlocked.Increment(ref skipCount);
                                                Interlocked.Increment(ref completedTasks);
                                                
                                                currentCompleted = completedTasks;
                                                progressPercent = currentCompleted * 100.0 / totalTasks;
                                                
                                                ExtractWindowModel.Dispatcher.Invoke(() =>
                                                {
                                                    var taskItem = new Models.ExtractTaskItem
                                                    {
                                                        Index = currentIndex.ToString(),
                                                        FileName = displayFileName,
                                                        FullFileName = _tmpFileName,
                                                        Status = "跳过",
                                                        OriginalSize = "--",
                                                        OutputSize = "--",
                                                        SizeChange = "--",
                                                        Duration = "--",
                                                        Progress = $"{progressPercent:F1}%"
                                                    };
                                                    ExtractWindowModel.TaskItems.Add(taskItem);
                                                });
                                                return;
                                            }

                                            // 先检查视频时长和获取视频信息
                                            IMediaAnalysis? mediaInfo = null;
                                            double totalDuration = 0;
                                            try
                                            {
                                                mediaInfo = await FFProbe.AnalyseAsync(currentVideo);
                                                totalDuration = mediaInfo.Duration.TotalSeconds;
                                                
                                                if (totalDuration < 20 && ExtractWindowModel.ExtractFrameMode == Models.ExtractFrameMode.DeleteFrame)
                                                {
                                                    string errorMsg = $"视频时长太短：{currentVideo}（{totalDuration:F2}秒），需要至少20秒";
                                                    LogUtils.Error(errorMsg);
                                                    errorMessages.Add(errorMsg);
                                                    
                                                    Interlocked.Increment(ref completedTasks);
                                                    currentCompleted = completedTasks;
                                                    progressPercent = currentCompleted * 100.0 / totalTasks;
                                                    
                                                    ExtractWindowModel.Dispatcher.Invoke(() =>
                                                    {
                                                        var taskItem = new Models.ExtractTaskItem
                                                        {
                                                            Index = currentIndex.ToString(),
                                                            FileName = displayFileName,
                                                            FullFileName = _tmpFileName,
                                                            Status = "失败",
                                                            OriginalSize = "--",
                                                            OutputSize = "--",
                                                            SizeChange = "--",
                                                            Duration = "--",
                                                            Progress = $"{progressPercent:F1}%"
                                                        };
                                                        ExtractWindowModel.TaskItems.Add(taskItem);
                                                    });
                                                    return;
                                                }
                                            }
                                            catch (Exception ex)
                                            {
                                                LogUtils.Error($"检查视频时长失败：{currentVideo}", ex);
                                                // 继续处理，让后续方法来处理错误
                                            }

                                            // 记录开始时间
                                            DateTime taskStartTime = DateTime.Now;
                                            
                                            // 根据选择的处理方式调用相应方法
                                            bool success = false;
                                            
                                            if (ExtractWindowModel.ExtractFrameMode == Models.ExtractFrameMode.DeleteFrame)
                                            {
                                                // 方案1：随机删除一个非关键帧（传入index确保每次位置不同）
                                                success = await VideoProcess.RemoveNonKeyFrameAsync(currentVideo, outputPath, currentIndex);
                                            }
                                            else if (ExtractWindowModel.ExtractFrameMode == Models.ExtractFrameMode.AddTransparentImage)
                                            {
                                                // 方案2：在随机位置添加透明图
                                                success = await VideoProcess.AddTransparentImageAsync(currentVideo, outputPath);
                                            }
                                            else
                                            {
                                                // 默认使用原来的方法（保留兼容性）
                                                success = await VideoProcess.RemoveFrameRandomeAsync(currentVideo, outputPath);
                                            }
                                            
                                            // 计算处理时间
                                            TimeSpan taskDuration = DateTime.Now - taskStartTime;
                                            
                                            // 更新完成计数
                                            Interlocked.Increment(ref completedTasks);
                                            currentCompleted = completedTasks;
                                            progressPercent = currentCompleted * 100.0 / totalTasks;
                                            
                                            // 再次检查文件是否存在
                                            if (File.Exists(outputPath))
                                            {
                                                FileInfo outputFileInfo = new FileInfo(outputPath);
                                                long outputSize = outputFileInfo.Length;
                                                Interlocked.Add(ref totalOutputSize, outputSize);
                                                Interlocked.Increment(ref successCount);
                                                
                                                double originalMB = originalSize / 1024.0 / 1024.0;
                                                double outputMB = outputSize / 1024.0 / 1024.0;
                                                double sizeDiff = outputSize - originalSize;
                                                double sizeDiffMB = Math.Abs(sizeDiff) / 1024.0 / 1024.0;
                                                string sizeChange = sizeDiff > 0 ? $"+{sizeDiffMB:F2}" : sizeDiff < 0 ? $"-{sizeDiffMB:F2}" : "0";
                                                string sizeChangeMB = sizeChange + "MB";
                                                
                                                string originalSizeStr = $"{originalMB:F2}MB";
                                                string outputSizeStr = $"{outputMB:F2}MB";
                                                string durationStr = $"{taskDuration.TotalSeconds:F1}s";
                                                
                                                successMessages.Add($"{currentVideo} (第{currentIndex}个) - 成功");
                                                LogUtils.Info($"处理成功：{currentVideo} -> {outputPath}, 大小={outputMB:F2}MB, 耗时={taskDuration.TotalSeconds:F2}秒");
                                                
                                                // 更新表格行
                                                ExtractWindowModel.Dispatcher.Invoke(() =>
                                                {
                                                    var taskItem = new Models.ExtractTaskItem
                                                    {
                                                        Index = currentIndex.ToString(),
                                                        FileName = displayFileName,
                                                        FullFileName = _tmpFileName,
                                                        Status = "成功",
                                                        OriginalSize = originalSizeStr,
                                                        OutputSize = outputSizeStr,
                                                        SizeChange = sizeChangeMB,
                                                        Duration = durationStr,
                                                        Progress = $"{progressPercent:F1}%"
                                                    };
                                                    ExtractWindowModel.TaskItems.Add(taskItem);
                                                });
                                            }
                                            else if (success)
                                            {
                                                LogUtils.Warn($"处理返回成功但文件不存在：{outputPath}");
                                                string errorMsg = $"{currentVideo} (第{currentIndex}个) - 返回成功但文件不存在";
                                                errorMessages.Add(errorMsg);
                                                
                                                ExtractWindowModel.Dispatcher.Invoke(() =>
                                                {
                                                    var taskItem = new Models.ExtractTaskItem
                                                    {
                                                        Index = currentIndex.ToString(),
                                                        FileName = displayFileName,
                                                        FullFileName = _tmpFileName,
                                                        Status = "警告",
                                                        OriginalSize = "--",
                                                        OutputSize = "--",
                                                        SizeChange = "--",
                                                        Duration = "--",
                                                        Progress = $"{progressPercent:F1}%"
                                                    };
                                                    ExtractWindowModel.TaskItems.Add(taskItem);
                                                });
                                            }
                                            else
                                            {
                                                string errorMsg = $"{currentVideo} (第{currentIndex}个) - 处理失败";
                                                LogUtils.Error($"{errorMsg} -> {outputPath}");
                                                errorMessages.Add(errorMsg);
                                                
                                                ExtractWindowModel.Dispatcher.Invoke(() =>
                                                {
                                                    var taskItem = new Models.ExtractTaskItem
                                                    {
                                                        Index = currentIndex.ToString(),
                                                        FileName = displayFileName,
                                                        FullFileName = _tmpFileName,
                                                        Status = "失败",
                                                        OriginalSize = "--",
                                                        OutputSize = "--",
                                                        SizeChange = "--",
                                                        Duration = "--",
                                                        Progress = $"{progressPercent:F1}%"
                                                    };
                                                    ExtractWindowModel.TaskItems.Add(taskItem);
                                                });
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            // 在异常处理中重新获取文件名等信息
                                            string originalFileNameForError = Path.GetFileNameWithoutExtension(currentVideo);
                                            string errorMsg = $"抽帧异常：{currentVideo} (第{currentIndex}个) - {ex.Message}";
                                            LogUtils.Error($"抽帧失败：{currentVideo} (第{currentIndex}个)", ex);
                                            errorMessages.Add(errorMsg);
                                            
                                            Interlocked.Increment(ref completedTasks);
                                            int currentCompletedForError = completedTasks;
                                            double progressPercentForError = currentCompletedForError * 100.0 / totalTasks;
                                            string displayFileNameForError = originalFileNameForError.Length > 15 ? originalFileNameForError.Substring(0, 12) + "..." : originalFileNameForError.PadRight(15);
                                            
                                            string modeSuffixForError2 = ExtractWindowModel.ExtractFrameMode == Models.ExtractFrameMode.DeleteFrame ? "方案1" : "方案2";
                                            string dateStrForError2 = DateTime.Now.ToString("yyyyMMdd");
                                            ExtractWindowModel.Dispatcher.Invoke(() =>
                                            {
                                                var taskItem = new Models.ExtractTaskItem
                                                {
                                                    Index = currentIndex.ToString(),
                                                    FileName = displayFileNameForError,
                                                    FullFileName = $"{originalFileNameForError}_{modeSuffixForError2}_{dateStrForError2}_{currentIndex:D4}{Path.GetExtension(currentVideo)}",
                                                    Status = "异常",
                                                    OriginalSize = "--",
                                                    OutputSize = "--",
                                                    SizeChange = "--",
                                                    Duration = "--",
                                                    Progress = $"{progressPercentForError:F1}%"
                                                };
                                                ExtractWindowModel.TaskItems.Add(taskItem);
                                            });
                                        }
                                        finally
                                        {
                                            semaphore.Release();
                                        }
                                    });
                                    _tasks.Add(_task);
                                }
                            }

                            await Task.WhenAll(_tasks);
                            
                            // 计算总耗时
                            TimeSpan totalDuration = DateTime.Now - startTime;
                            
                            // 统计实际生成的文件数量
                            int actualFileCount = 0;
                            string outputDir = "";
                            if (ExtractWindowModel.videos.Length > 0)
                            {
                                string firstVideo = ExtractWindowModel.videos[0];
                                string videoDir = Path.GetDirectoryName(firstVideo) ?? "";
                                outputDir = Path.Combine(videoDir, "out");
                                
                                if (Directory.Exists(outputDir))
                                {
                                    actualFileCount = Directory.GetFiles(outputDir, "*.mp4").Length;
                                    LogUtils.Info($"输出目录 {outputDir} 中共有 {actualFileCount} 个视频文件");
                                }
                            }
                            
                            // 构建最终详细信息
                            double totalOriginalMB = totalOriginalSize / 1024.0 / 1024.0;
                            double totalOutputMB = totalOutputSize / 1024.0 / 1024.0;
                            double totalSizeDiff = totalOutputSize - totalOriginalSize;
                            double totalSizeDiffMB = Math.Abs(totalSizeDiff) / 1024.0 / 1024.0;
                            string totalSizeChange = totalSizeDiff > 0 ? $"+{totalSizeDiffMB:F2}MB" : totalSizeDiff < 0 ? $"-{totalSizeDiffMB:F2}MB" : "0MB";
                            
                            string summaryInfo = $"\n处理完成！\n" +
                                $"处理方案：{modeText} | 总任务数：{totalTasks} 个\n" +
                                $"成功数量：{successCount} 个 | 失败数量：{errorMessages.Count} 个 | 跳过数量：{skipCount} 个\n" +
                                $"实际生成：{actualFileCount} 个文件\n" +
                                $"总原始大小：{totalOriginalMB:F2}MB | 总输出大小：{totalOutputMB:F2}MB | 大小变化：{totalSizeChange}\n" +
                                $"总耗时：{totalDuration.TotalSeconds:F1}秒 ({totalDuration.TotalMinutes:F1}分钟) | 平均速度：{(successCount > 0 ? totalDuration.TotalSeconds / successCount : 0):F2}秒/个\n" +
                                $"输出目录：{outputDir}\n" +
                                $"完成时间：{DateTime.Now:yyyy-MM-dd HH:mm:ss}";
                            
                            ExtractWindowModel.Dispatcher.Invoke(() =>
                            {
                                ExtractWindowModel.HelpInfo += $"\n{summaryInfo}";
                                
                                // 如果有错误信息，显示汇总
                                if (errorMessages.Count > 0)
                                {
                                    ExtractWindowModel.HelpInfo += $"\n错误信息（共{errorMessages.Count}个）：";
                                    foreach (var error in errorMessages)
                                    {
                                        ExtractWindowModel.HelpInfo += $"\n  • {error}";
                                    }
                                }
                                
                                ExtractWindowModel.IsStart = false;
                                ExtractWindowModel.IsCanOperate = true;
                            });
                            LogUtils.Info($"处理完成，成功={successCount}, 失败={errorMessages.Count}, 跳过={skipCount}, 总耗时={totalDuration.TotalSeconds:F1}秒");
                        });
                    }
                },

                BtnStartVideoModifyCommand = new Command()
                {
                    DoExcue = obj =>
                    {
                        ExtractWindowModel.HelpInfo = "";


                        SemaphoreSlim semaphore = new(10); // Limit to 3 threads

                        List<Task> _tasks = [];

                        ExtractWindowModel.videos.ForEach(async (video) =>
                        {
                            await semaphore.WaitAsync(); // Wait when more than 3 threads are running
                            var _task = Task.Run(async () =>
                            {
                                try
                                {
                                    // 实例化并调用
                                    var remover = new VideoProcess();
                                    // 删除4秒处的帧（需根据实际帧位置调整）
                                    string _tmpPath = Path.GetDirectoryName(video) ?? "";
                                    string _tmpFileName = $"{(new Random()).Next(10000, 99999)}{Path.GetFileName(video)}";

                                    string outPath = Path.Combine(_tmpPath, "out");
                                    if (!Path.Exists(outPath))
                                    {
                                        Directory.CreateDirectory(outPath);
                                    }

                                    VideoProcess.ModifyByMetadata(video, $"{_tmpPath}\\out\\modify{_tmpFileName}");
                                }
                                finally
                                {
                                    semaphore.Release(); // Work is done, signal to semaphore that more work is possible
                                }
                            });
                            _tasks.Add(_task);
                        });

                        Task.WhenAll(_tasks).ContinueWith((task) =>
                        {
                            ExtractWindowModel.HelpInfo = "全部完成!";
                        });
                    }
                }
            };
        }

        private void ListFolder()
        {
            DirectoryInfo dir = new(ExtractWindowModel.FolderPath);
            try
            {
                DirectoryInfo dirD = dir as DirectoryInfo;

                //获取文件夹下所有视频文件

                ExtractWindowModel.videos = Directory.GetFiles(dirD.FullName, "*.mp4");
                ExtractWindowModel.SetCanStart();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
        }
    }
}
