using System.Diagnostics;

namespace NavisworksTransport.Core.UIUpdate
{
    /// <summary>
    /// UI更新事务实现
    /// 提供事务性的UI更新操作，支持提交和回滚机制
    /// </summary>
    public class UIUpdateTransaction : IUIUpdateTransaction
    {
        #region 字段和属性

        private readonly List<IUIUpdate> _updates;
        private readonly List<UIUpdateResult> _executedResults;
        private readonly object _lockObject = new object();
        private readonly int _timeoutMilliseconds;
        private volatile bool _isDisposed = false;

        /// <summary>
        /// 事务唯一标识符
        /// </summary>
        public string Id { get; private set; }

        /// <summary>
        /// 事务名称
        /// </summary>
        public string Name { get; private set; }

        /// <summary>
        /// 事务状态
        /// </summary>
        public UITransactionStatus Status { get; private set; }

        /// <summary>
        /// 事务中包含的更新操作数量
        /// </summary>
        public int UpdateCount => _updates.Count;

        /// <summary>
        /// 事务开始时间
        /// </summary>
        public DateTime StartTime { get; private set; }

        #endregion

        #region 构造函数

        /// <summary>
        /// 初始化UI更新事务
        /// </summary>
        /// <param name="name">事务名称</param>
        /// <param name="timeoutMilliseconds">超时时间（毫秒）</param>
        public UIUpdateTransaction(string name = null, int timeoutMilliseconds = 30000)
        {
            Id = Guid.NewGuid().ToString();
            Name = name ?? $"Transaction_{DateTime.Now:HHmmss}";
            Status = UITransactionStatus.Active;
            StartTime = DateTime.UtcNow;
            _timeoutMilliseconds = timeoutMilliseconds;

            _updates = new List<IUIUpdate>();
            _executedResults = new List<UIUpdateResult>();

            LogManager.Info($"[UITransaction] 创建事务: {Name} ({Id})");
        }

        #endregion

        #region IUIUpdateTransaction接口实现

        /// <summary>
        /// 提交事务
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        public async Task<UITransactionResult> CommitAsync(CancellationToken cancellationToken = default)
        {
            if (_isDisposed)
            {
                return CreateFailureResult("事务已被释放");
            }

            if (Status != UITransactionStatus.Active)
            {
                return CreateFailureResult($"事务状态不正确，无法提交: {Status}");
            }

            var stopwatch = Stopwatch.StartNew();

            try
            {
                LogManager.Info($"[UITransaction] 开始提交事务: {Name}");
                SetStatus(UITransactionStatus.Committing);

                // 检查超时
                if (DateTime.UtcNow - StartTime > TimeSpan.FromMilliseconds(_timeoutMilliseconds))
                {
                    SetStatus(UITransactionStatus.Failed);
                    return CreateFailureResult("事务超时");
                }

                // 执行所有更新操作
                var allResults = new List<UIUpdateResult>();
                var exceptions = new List<Exception>();

                foreach (var update in _updates)
                {
                    try
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        var context = UIUpdateContext.Default();
                        context.TimeoutMilliseconds = Math.Max(1000, _timeoutMilliseconds / Math.Max(1, _updates.Count));

                        var result = await update.ExecuteAsync(context, cancellationToken);
                        allResults.Add(result);
                        _executedResults.Add(result);

                        if (!result.IsSuccess)
                        {
                            LogManager.Warning($"[UITransaction] 事务{Name}中的更新操作{update.Name}失败: {result.Message}");
                            if (result.Exception != null)
                            {
                                exceptions.Add(result.Exception);
                            }
                        }
                    }
                    catch (OperationCanceledException)
                    {
                        SetStatus(UITransactionStatus.Failed);
                        return CreateFailureResult("事务提交被取消");
                    }
                    catch (Exception ex)
                    {
                        LogManager.Error($"[UITransaction] 事务{Name}中的更新操作{update.Name}发生异常", ex);
                        exceptions.Add(ex);
                        allResults.Add(UIUpdateResult.Failure($"执行异常: {ex.Message}", ex, update.Id));
                    }
                }

                // 检查所有操作是否成功
                var successCount = allResults.Count(r => r.IsSuccess);
                var failureCount = allResults.Count - successCount;

                if (failureCount == 0)
                {
                    SetStatus(UITransactionStatus.Committed);
                    LogManager.Info($"[UITransaction] 事务{Name}提交成功，执行了{successCount}个操作");

                    return new UITransactionResult
                    {
                        IsSuccess = true,
                        TransactionId = Id,
                        TransactionName = Name,
                        FinalStatus = Status,
                        Message = $"事务提交成功，执行了{successCount}个操作",
                        UpdateResults = new UIBatchUpdateResult
                        {
                            IsSuccess = true,
                            TotalCount = allResults.Count,
                            SuccessCount = successCount,
                            FailureCount = failureCount,
                            Results = allResults,
                            ElapsedMilliseconds = stopwatch.ElapsedMilliseconds
                        },
                        ElapsedMilliseconds = stopwatch.ElapsedMilliseconds
                    };
                }
                else
                {
                    // 有操作失败，尝试回滚
                    LogManager.Warning($"[UITransaction] 事务{Name}中有{failureCount}个操作失败，开始回滚");

                    var rollbackResult = await RollbackAsync(cancellationToken);
                    rollbackResult.UpdateResults = new UIBatchUpdateResult
                    {
                        IsSuccess = false,
                        TotalCount = allResults.Count,
                        SuccessCount = successCount,
                        FailureCount = failureCount,
                        Results = allResults,
                        AggregateException = exceptions.Count > 0 ? new AggregateException(exceptions) : null,
                        ElapsedMilliseconds = stopwatch.ElapsedMilliseconds
                    };

                    return rollbackResult;
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[UITransaction] 事务{Name}提交过程中发生异常", ex);
                SetStatus(UITransactionStatus.Failed);

                try
                {
                    await RollbackAsync(cancellationToken);
                }
                catch (Exception rollbackEx)
                {
                    LogManager.Error($"[UITransaction] 事务{Name}回滚失败", rollbackEx);
                }

                return CreateFailureResult($"事务提交失败: {ex.Message}", ex, stopwatch.ElapsedMilliseconds);
            }
            finally
            {
                stopwatch.Stop();
            }
        }

        /// <summary>
        /// 回滚事务
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        public async Task<UITransactionResult> RollbackAsync(CancellationToken cancellationToken = default)
        {
            if (_isDisposed)
            {
                return CreateFailureResult("事务已被释放");
            }

            if (Status == UITransactionStatus.RolledBack)
            {
                return CreateSuccessResult("事务已经回滚", UITransactionStatus.RolledBack);
            }

            if (Status == UITransactionStatus.Committed)
            {
                return CreateFailureResult("已提交的事务不能回滚");
            }

            var stopwatch = Stopwatch.StartNew();

            try
            {
                LogManager.Info($"[UITransaction] 开始回滚事务: {Name}");
                SetStatus(UITransactionStatus.RollingBack);

                var rollbackResults = new List<UIUpdateResult>();
                var exceptions = new List<Exception>();

                // 按相反顺序回滚已执行的操作
                var executedOperations = _executedResults.Where(r => r.IsSuccess).ToList();
                var correspondingUpdates = new List<IUIUpdate>();

                // 找到对应的成功执行的更新操作
                foreach (var result in executedOperations)
                {
                    var update = _updates.FirstOrDefault(u => u.Id == result.UpdateId);
                    if (update != null && update.SupportsRollback)
                    {
                        correspondingUpdates.Add(update);
                    }
                }

                // 反向回滚
                correspondingUpdates.Reverse();

                foreach (var update in correspondingUpdates)
                {
                    try
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        var context = UIUpdateContext.Default();
                        context.TimeoutMilliseconds = Math.Max(1000, _timeoutMilliseconds / Math.Max(1, correspondingUpdates.Count));

                        var rollbackResult = await update.RollbackAsync(context, cancellationToken);
                        rollbackResults.Add(rollbackResult);

                        if (!rollbackResult.IsSuccess)
                        {
                            LogManager.Warning($"[UITransaction] 回滚操作{update.Name}失败: {rollbackResult.Message}");
                            if (rollbackResult.Exception != null)
                            {
                                exceptions.Add(rollbackResult.Exception);
                            }
                        }
                    }
                    catch (OperationCanceledException)
                    {
                        SetStatus(UITransactionStatus.Failed);
                        return CreateFailureResult("事务回滚被取消");
                    }
                    catch (Exception ex)
                    {
                        LogManager.Error($"[UITransaction] 回滚操作{update.Name}时发生异常", ex);
                        exceptions.Add(ex);
                        rollbackResults.Add(UIUpdateResult.Failure($"回滚异常: {ex.Message}", ex, update.Id));
                    }
                }

                // 检查回滚结果
                var successCount = rollbackResults.Count(r => r.IsSuccess);
                var failureCount = rollbackResults.Count - successCount;

                SetStatus(UITransactionStatus.RolledBack);

                var message = failureCount == 0 
                    ? $"事务回滚成功，回滚了{successCount}个操作"
                    : $"事务回滚完成，成功{successCount}个，失败{failureCount}个";

                LogManager.Info($"[UITransaction] {message}");

                return new UITransactionResult
                {
                    IsSuccess = failureCount == 0,
                    TransactionId = Id,
                    TransactionName = Name,
                    FinalStatus = Status,
                    Message = message,
                    UpdateResults = new UIBatchUpdateResult
                    {
                        IsSuccess = failureCount == 0,
                        TotalCount = rollbackResults.Count,
                        SuccessCount = successCount,
                        FailureCount = failureCount,
                        Results = rollbackResults,
                        AggregateException = exceptions.Count > 0 ? new AggregateException(exceptions) : null,
                        ElapsedMilliseconds = stopwatch.ElapsedMilliseconds
                    },
                    ElapsedMilliseconds = stopwatch.ElapsedMilliseconds
                };
            }
            catch (Exception ex)
            {
                LogManager.Error($"[UITransaction] 事务{Name}回滚过程中发生异常", ex);
                SetStatus(UITransactionStatus.Failed);
                return CreateFailureResult($"事务回滚失败: {ex.Message}", ex, stopwatch.ElapsedMilliseconds);
            }
            finally
            {
                stopwatch.Stop();
            }
        }

        /// <summary>
        /// 添加更新操作到事务
        /// </summary>
        /// <param name="update">UI更新操作</param>
        public void AddUpdate(IUIUpdate update)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException(nameof(UIUpdateTransaction));
            }

            if (Status != UITransactionStatus.Active)
            {
                throw new InvalidOperationException($"事务状态不正确，无法添加操作: {Status}");
            }

            if (update == null)
            {
                throw new ArgumentNullException(nameof(update));
            }

            lock (_lockObject)
            {
                _updates.Add(update);
            }

            LogManager.Debug($"[UITransaction] 向事务{Name}添加更新操作: {update.Name}");
        }

        /// <summary>
        /// 批量添加更新操作到事务
        /// </summary>
        /// <param name="updates">UI更新操作集合</param>
        public void AddUpdates(IEnumerable<IUIUpdate> updates)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException(nameof(UIUpdateTransaction));
            }

            if (Status != UITransactionStatus.Active)
            {
                throw new InvalidOperationException($"事务状态不正确，无法添加操作: {Status}");
            }

            if (updates == null)
            {
                throw new ArgumentNullException(nameof(updates));
            }

            var updateList = updates.ToList();
            if (updateList.Count == 0)
            {
                return;
            }

            lock (_lockObject)
            {
                _updates.AddRange(updateList);
            }

            LogManager.Debug($"[UITransaction] 向事务{Name}批量添加{updateList.Count}个更新操作");
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 设置事务状态
        /// </summary>
        /// <param name="newStatus">新状态</param>
        private void SetStatus(UITransactionStatus newStatus)
        {
            var oldStatus = Status;
            Status = newStatus;

            if (oldStatus != newStatus)
            {
                LogManager.Debug($"[UITransaction] 事务{Name}状态变化: {oldStatus} -> {newStatus}");
            }
        }

        /// <summary>
        /// 创建成功结果
        /// </summary>
        /// <param name="message">消息</param>
        /// <param name="finalStatus">最终状态</param>
        /// <param name="elapsedMilliseconds">耗时</param>
        /// <returns>事务结果</returns>
        private UITransactionResult CreateSuccessResult(string message, UITransactionStatus finalStatus, long elapsedMilliseconds = 0)
        {
            return new UITransactionResult
            {
                IsSuccess = true,
                TransactionId = Id,
                TransactionName = Name,
                FinalStatus = finalStatus,
                Message = message,
                ElapsedMilliseconds = elapsedMilliseconds
            };
        }

        /// <summary>
        /// 创建失败结果
        /// </summary>
        /// <param name="message">错误消息</param>
        /// <param name="exception">异常</param>
        /// <param name="elapsedMilliseconds">耗时</param>
        /// <returns>事务结果</returns>
        private UITransactionResult CreateFailureResult(string message, Exception exception = null, long elapsedMilliseconds = 0)
        {
            return new UITransactionResult
            {
                IsSuccess = false,
                TransactionId = Id,
                TransactionName = Name,
                FinalStatus = UITransactionStatus.Failed,
                Message = message,
                Exception = exception,
                ElapsedMilliseconds = elapsedMilliseconds
            };
        }

        #endregion

        #region IDisposable实现

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            if (_isDisposed)
            {
                return;
            }

            try
            {
                // 如果事务仍处于活动状态，尝试回滚
                if (Status == UITransactionStatus.Active || Status == UITransactionStatus.Committing)
                {
                    LogManager.Warning($"[UITransaction] 事务{Name}在释放时仍处于{Status}状态，尝试回滚");
                    _ = RollbackAsync();
                }

                _isDisposed = true;
                LogManager.Debug($"[UITransaction] 事务{Name}已释放");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[UITransaction] 释放事务{Name}时发生异常", ex);
            }
        }

        #endregion

        #region 重写方法

        /// <summary>
        /// 获取字符串表示
        /// </summary>
        public override string ToString()
        {
            return $"UITransaction: {Name} ({Id}) - {Status} - {UpdateCount} updates";
        }

        #endregion
    }
}