using System.ComponentModel;

namespace NavisworksTransport.Core.UIUpdate.Updates
{
    /// <summary>
    /// 属性更新操作
    /// 支持WPF和WinForms控件的属性更新，提供线程安全的属性设置
    /// </summary>
    public class PropertyUpdateOperation : UIUpdateBase
    {
        #region 字段和属性

        /// <summary>
        /// 目标对象
        /// </summary>
        public object Target { get; }

        /// <summary>
        /// 属性名称
        /// </summary>
        public string PropertyName { get; }

        /// <summary>
        /// 新值
        /// </summary>
        public object NewValue { get; }

        /// <summary>
        /// 原始值（用于回滚）
        /// </summary>
        public object OriginalValue { get; private set; }

        /// <summary>
        /// 是否已保存原始值
        /// </summary>
        private bool _originalValueSaved = false;

        #endregion

        #region 构造函数

        /// <summary>
        /// 初始化属性更新操作
        /// </summary>
        /// <param name="target">目标对象</param>
        /// <param name="propertyName">属性名称</param>
        /// <param name="newValue">新值</param>
        /// <param name="priority">操作优先级</param>
        public PropertyUpdateOperation(object target, string propertyName, object newValue, UIUpdatePriority priority = UIUpdatePriority.Normal)
            : base($"PropertyUpdate_{propertyName}", $"更新属性{propertyName}", priority)
        {
            Target = target ?? throw new ArgumentNullException(nameof(target));
            PropertyName = propertyName ?? throw new ArgumentNullException(nameof(propertyName));
            NewValue = newValue;

            // 自动检测目标框架
            TargetFramework = DetectTargetFramework(target);
            SupportsRollback = true;
        }

        #endregion

        #region 受保护方法重写

        /// <summary>
        /// 内部验证逻辑
        /// </summary>
        /// <param name="context">更新上下文</param>
        /// <returns>验证结果</returns>
        protected override UIUpdateValidationResult ValidateInternal(UIUpdateContext context)
        {
            try
            {
                // 检查目标对象是否为空
                if (Target == null)
                {
                    return UIUpdateValidationResult.Failure("目标对象不能为空");
                }

                // 检查属性名称
                if (string.IsNullOrEmpty(PropertyName))
                {
                    return UIUpdateValidationResult.Failure("属性名称不能为空");
                }

                // 检查属性是否存在
                var propertyInfo = Target.GetType().GetProperty(PropertyName);
                if (propertyInfo == null)
                {
                    return UIUpdateValidationResult.Failure($"目标对象不存在属性: {PropertyName}");
                }

                // 检查属性是否可写
                if (!propertyInfo.CanWrite)
                {
                    return UIUpdateValidationResult.Failure($"属性{PropertyName}是只读的");
                }

                // 检查类型兼容性
                if (NewValue != null && !propertyInfo.PropertyType.IsAssignableFrom(NewValue.GetType()))
                {
                    // 尝试类型转换
                    if (!CanConvertType(NewValue, propertyInfo.PropertyType))
                    {
                        return UIUpdateValidationResult.Failure($"值类型{NewValue.GetType().Name}与属性类型{propertyInfo.PropertyType.Name}不兼容");
                    }
                }

                return UIUpdateValidationResult.Success();
            }
            catch (Exception ex)
            {
                return UIUpdateValidationResult.Failure($"验证属性更新时发生异常: {ex.Message}");
            }
        }

        /// <summary>
        /// 执行前置处理
        /// </summary>
        /// <param name="context">更新上下文</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>处理结果</returns>
        protected override async Task<UIUpdateResult> PreExecuteAsync(UIUpdateContext context, CancellationToken cancellationToken)
        {
            try
            {
                // 保存原始值用于回滚
                if (!_originalValueSaved && SupportsRollback)
                {
                    var propertyInfo = Target.GetType().GetProperty(PropertyName);
                    OriginalValue = propertyInfo.GetValue(Target);
                    _originalValueSaved = true;
                    LogInfo($"已保存属性{PropertyName}的原始值: {OriginalValue}");
                }

                return await Task.FromResult(UIUpdateResult.Success("前置处理完成", Id));
            }
            catch (Exception ex)
            {
                return UIUpdateResult.Failure($"前置处理失败: {ex.Message}", ex, Id);
            }
        }

        /// <summary>
        /// 执行主要逻辑
        /// </summary>
        /// <param name="context">更新上下文</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>执行结果</returns>
        protected override async Task<UIUpdateResult> ExecuteInternalAsync(UIUpdateContext context, CancellationToken cancellationToken)
        {
            try
            {
                LogInfo($"更新属性{PropertyName}: {OriginalValue} -> {NewValue}");

                // 根据目标框架选择更新方式
                switch (TargetFramework)
                {
                    case UIFrameworkType.WPF:
                        return await UpdateWpfPropertyAsync(cancellationToken);

                    case UIFrameworkType.WinForms:
                        return await UpdateWinFormsPropertyAsync(cancellationToken);

                    case UIFrameworkType.Auto:
                    case UIFrameworkType.Hybrid:
                        return await UpdatePropertyAutoAsync(cancellationToken);

                    default:
                        return UIUpdateResult.Failure($"不支持的UI框架类型: {TargetFramework}", null, Id);
                }
            }
            catch (Exception ex)
            {
                LogError($"更新属性{PropertyName}失败", ex);
                return UIUpdateResult.Failure($"更新属性失败: {ex.Message}", ex, Id);
            }
        }

        /// <summary>
        /// 内部回滚逻辑
        /// </summary>
        /// <param name="context">更新上下文</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>回滚结果</returns>
        protected override async Task<UIUpdateResult> RollbackInternalAsync(UIUpdateContext context, CancellationToken cancellationToken)
        {
            try
            {
                if (!_originalValueSaved)
                {
                    return UIUpdateResult.Failure("无法回滚，原始值未保存", null, Id);
                }

                LogInfo($"回滚属性{PropertyName}: {NewValue} -> {OriginalValue}");

                // 创建一个新的属性更新操作来执行回滚
                var rollbackOperation = new PropertyUpdateOperation(Target, PropertyName, OriginalValue);
                var rollbackResult = await rollbackOperation.ExecuteInternalAsync(context, cancellationToken);

                if (rollbackResult.IsSuccess)
                {
                    return UIUpdateResult.Success($"成功回滚属性{PropertyName}", Id);
                }
                else
                {
                    return UIUpdateResult.Failure($"回滚属性{PropertyName}失败: {rollbackResult.Message}", null, Id);
                }
            }
            catch (Exception ex)
            {
                LogError($"回滚属性{PropertyName}时发生异常", ex);
                return UIUpdateResult.Failure($"回滚失败: {ex.Message}", ex, Id);
            }
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 检测目标框架类型
        /// </summary>
        /// <param name="target">目标对象</param>
        /// <returns>框架类型</returns>
        private UIFrameworkType DetectTargetFramework(object target)
        {
            if (target is DependencyObject || target is INotifyPropertyChanged)
            {
                return UIFrameworkType.WPF;
            }
            
            if (target is Control)
            {
                return UIFrameworkType.WinForms;
            }

            return UIFrameworkType.Auto;
        }

        /// <summary>
        /// 检查是否可以进行类型转换
        /// </summary>
        /// <param name="value">要转换的值</param>
        /// <param name="targetType">目标类型</param>
        /// <returns>是否可以转换</returns>
        private bool CanConvertType(object value, Type targetType)
        {
            try
            {
                if (value == null)
                {
                    return !targetType.IsValueType || Nullable.GetUnderlyingType(targetType) != null;
                }

                var converter = TypeDescriptor.GetConverter(targetType);
                return converter.CanConvertFrom(value.GetType());
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 转换值类型
        /// </summary>
        /// <param name="value">要转换的值</param>
        /// <param name="targetType">目标类型</param>
        /// <returns>转换后的值</returns>
        private object ConvertValue(object value, Type targetType)
        {
            if (value == null)
            {
                return null;
            }

            if (targetType.IsAssignableFrom(value.GetType()))
            {
                return value;
            }

            try
            {
                var converter = TypeDescriptor.GetConverter(targetType);
                if (converter.CanConvertFrom(value.GetType()))
                {
                    return converter.ConvertFrom(value);
                }

                return Convert.ChangeType(value, targetType);
            }
            catch (Exception ex)
            {
                throw new InvalidCastException($"无法将值{value}从类型{value.GetType().Name}转换为{targetType.Name}", ex);
            }
        }

        /// <summary>
        /// 更新WPF属性
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>更新结果</returns>
        private async Task<UIUpdateResult> UpdateWpfPropertyAsync(CancellationToken cancellationToken)
        {
            var tcs = new TaskCompletionSource<UIUpdateResult>();

            try
            {
                if (Target is DependencyObject depObj)
                {
                    // 在UI线程上执行WPF属性更新
                    Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        try
                        {
                            var propertyInfo = Target.GetType().GetProperty(PropertyName);
                            var convertedValue = ConvertValue(NewValue, propertyInfo.PropertyType);
                            propertyInfo.SetValue(Target, convertedValue);
                            
                            tcs.SetResult(UIUpdateResult.Success($"WPF属性{PropertyName}更新成功", Id));
                        }
                        catch (Exception ex)
                        {
                            tcs.SetResult(UIUpdateResult.Failure($"WPF属性更新失败: {ex.Message}", ex, Id));
                        }
                    }));
                }
                else
                {
                    // 普通属性更新
                    var propertyInfo = Target.GetType().GetProperty(PropertyName);
                    var convertedValue = ConvertValue(NewValue, propertyInfo.PropertyType);
                    propertyInfo.SetValue(Target, convertedValue);
                    
                    tcs.SetResult(UIUpdateResult.Success($"属性{PropertyName}更新成功", Id));
                }

                return await tcs.Task;
            }
            catch (Exception ex)
            {
                return UIUpdateResult.Failure($"WPF属性更新异常: {ex.Message}", ex, Id);
            }
        }

        /// <summary>
        /// 更新WinForms属性
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>更新结果</returns>
        private async Task<UIUpdateResult> UpdateWinFormsPropertyAsync(CancellationToken cancellationToken)
        {
            var tcs = new TaskCompletionSource<UIUpdateResult>();

            try
            {
                if (Target is Control control)
                {
                    // 在UI线程上执行WinForms属性更新
                    if (control.InvokeRequired)
                    {
                        control.BeginInvoke(new Action(() =>
                        {
                            try
                            {
                                var propertyInfo = Target.GetType().GetProperty(PropertyName);
                                var convertedValue = ConvertValue(NewValue, propertyInfo.PropertyType);
                                propertyInfo.SetValue(Target, convertedValue);
                                
                                tcs.SetResult(UIUpdateResult.Success($"WinForms属性{PropertyName}更新成功", Id));
                            }
                            catch (Exception ex)
                            {
                                tcs.SetResult(UIUpdateResult.Failure($"WinForms属性更新失败: {ex.Message}", ex, Id));
                            }
                        }));
                    }
                    else
                    {
                        var propertyInfo = Target.GetType().GetProperty(PropertyName);
                        var convertedValue = ConvertValue(NewValue, propertyInfo.PropertyType);
                        propertyInfo.SetValue(Target, convertedValue);
                        
                        tcs.SetResult(UIUpdateResult.Success($"WinForms属性{PropertyName}更新成功", Id));
                    }
                }
                else
                {
                    // 普通属性更新
                    var propertyInfo = Target.GetType().GetProperty(PropertyName);
                    var convertedValue = ConvertValue(NewValue, propertyInfo.PropertyType);
                    propertyInfo.SetValue(Target, convertedValue);
                    
                    tcs.SetResult(UIUpdateResult.Success($"属性{PropertyName}更新成功", Id));
                }

                return await tcs.Task;
            }
            catch (Exception ex)
            {
                return UIUpdateResult.Failure($"WinForms属性更新异常: {ex.Message}", ex, Id);
            }
        }

        /// <summary>
        /// 自动检测并更新属性
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>更新结果</returns>
        private async Task<UIUpdateResult> UpdatePropertyAutoAsync(CancellationToken cancellationToken)
        {
            // 首先尝试WPF方式
            if (Target is DependencyObject)
            {
                return await UpdateWpfPropertyAsync(cancellationToken);
            }

            // 然后尝试WinForms方式
            if (Target is Control)
            {
                return await UpdateWinFormsPropertyAsync(cancellationToken);
            }

            // 直接属性更新
            try
            {
                var propertyInfo = Target.GetType().GetProperty(PropertyName);
                var convertedValue = ConvertValue(NewValue, propertyInfo.PropertyType);
                propertyInfo.SetValue(Target, convertedValue);
                
                return UIUpdateResult.Success($"属性{PropertyName}更新成功", Id);
            }
            catch (Exception ex)
            {
                return UIUpdateResult.Failure($"属性更新失败: {ex.Message}", ex, Id);
            }
        }

        #endregion
    }
}