using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using NavisworksTransport.UI.WPF.Converters;
using NavisworksTransport.Utils;
using NavisworksTransport.Utils.CoordinateSystem;

using System.Numerics;

namespace NavisworksTransport.UI.WPF.Views
{
    public partial class EditRotationWindow : Window, INotifyPropertyChanged
    {
        private enum RotationAxisTarget
        {
            X,
            Y,
            Z
        }

        private double _rotationXDegrees;
        private double _rotationYDegrees;
        private double _rotationZDegrees;
        private double _groundPathLiftHeightInMeters;
        private RotationAxisTarget _activeAxisTarget = RotationAxisTarget.Z;
        private ObjectStartPlacementRequest _adjustmentRequest;
        private readonly ObjectPassageProjectionOptimizationRequest _autoAdjustmentRequest;
        private readonly Func<ObjectPassageProjectionOptimizationResult> _autoAdjustmentProvider;
        private readonly Func<Vector3, ObjectPassageProjectionOptimizationResult> _alignToGroundProvider;
        private readonly bool _isGroundLiftEnabled;
        private double _vehicleHeightInMeters = 0.15;
        private bool _requireWidthLarger = false;
        private bool _isAlignToGroundResult;
        private bool _alignToGroundRequested = false;

        /// <summary>
        /// 门型偏好：true=宽>高，false=高>宽（默认）
        /// </summary>
        public bool RequireWidthLarger
        {
            get => _requireWidthLarger;
            set => _requireWidthLarger = value;
        }

        public (double sx, double sy, double sz)? AutoAdjustAabbSizes { get; set; }

        public bool AlignToGroundRequested => _alignToGroundRequested;
        public bool IsAlignToGroundResult { get => _isAlignToGroundResult; set => _isAlignToGroundResult = value; }

        public double VehicleHeightInMeters
        {
            get => _vehicleHeightInMeters;
            set => _vehicleHeightInMeters = value;
        }

        public double RotationXDegrees
        {
            get => _rotationXDegrees;
            set
            {
                if (_rotationXDegrees != value)
                {
                    _rotationXDegrees = value;
                    OnPropertyChanged();
                    OnPropertyChanged(nameof(RotationCorrection));
                }
            }
        }

        public double RotationYDegrees
        {
            get => _rotationYDegrees;
            set
            {
                if (_rotationYDegrees != value)
                {
                    _rotationYDegrees = value;
                    OnPropertyChanged();
                    OnPropertyChanged(nameof(RotationCorrection));
                }
            }
        }

        public double RotationZDegrees
        {
            get => _rotationZDegrees;
            set
            {
                if (_rotationZDegrees != value)
                {
                    _rotationZDegrees = value;
                    OnPropertyChanged();
                    OnPropertyChanged(nameof(RotationCorrection));
                }
            }
        }

        public LocalEulerRotationCorrection RotationCorrection =>
            new LocalEulerRotationCorrection(RotationXDegrees, RotationYDegrees, RotationZDegrees);

        public double GroundPathLiftHeightInMeters
        {
            get => _groundPathLiftHeightInMeters;
            set
            {
                if (Math.Abs(_groundPathLiftHeightInMeters - value) > 1e-9)
                {
                    _groundPathLiftHeightInMeters = value;
                    OnPropertyChanged();
                }
            }
        }

        public bool IsGroundLiftEnabled => _isGroundLiftEnabled;

        public string GroundLiftHint => _isGroundLiftEnabled
            ? "沿垂直方向偏移，正值向上、负值向下，适用于所有路径类型。"
            : "上下偏移当前不可用。";

        public ObjectStartPlacementRequest AdjustmentRequest => _adjustmentRequest;

        public EditRotationWindow(
            LocalEulerRotationCorrection currentRotation,
            double currentGroundLiftHeightInMeters,
            bool isGroundLiftEnabled,
            ObjectPassageProjectionOptimizationRequest autoAdjustmentRequest = null,
            Func<ObjectPassageProjectionOptimizationResult> autoAdjustmentProvider = null,
            Func<Vector3, ObjectPassageProjectionOptimizationResult> alignToGroundProvider = null)
        {
            try
            {
                InitializeComponent();
                RotationXDegrees = currentRotation.XDegrees;
                RotationYDegrees = currentRotation.YDegrees;
                RotationZDegrees = currentRotation.ZDegrees;
                _isGroundLiftEnabled = isGroundLiftEnabled;
                _autoAdjustmentRequest = autoAdjustmentRequest;
                _autoAdjustmentProvider = autoAdjustmentProvider;
                _alignToGroundProvider = alignToGroundProvider;
                // 默认上下偏移 = 物流车高度（若未设置过）
                GroundPathLiftHeightInMeters = Math.Abs(currentGroundLiftHeightInMeters) < 1e-9
                    ? VehicleHeightInMeters
                    : currentGroundLiftHeightInMeters;
                _adjustmentRequest = ObjectStartPlacementRequest.CreateRotationCorrection(currentRotation, currentGroundLiftHeightInMeters);
                DataContext = this;
                Loaded += (sender, args) => ZAxisTextBox.Focus();
            }
            catch (Exception ex)
            {
                LogManager.Error($"角度修正对话框初始化失败: {ex.Message}", ex);
                MessageBox.Show($"角度修正对话框初始化失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void OnYAxisRotateClick(object sender, RoutedEventArgs e)
        {
            double newValue = RotationYDegrees + 90.0;
            RotationYDegrees = NormalizeDisplayDegrees(newValue);
            YAxisTextBox.Focus();
            YAxisTextBox.SelectAll();
            LogManager.Debug($"[Y轴旋转] 增加 90°: {newValue:F3} → {RotationYDegrees:F3}");
        }

        private void OnAutoAdjustClick(object sender, RoutedEventArgs e)
        {
            if (_autoAdjustmentProvider == null && _autoAdjustmentRequest == null)
            {
                MessageBox.Show("当前路径或物体尺寸不足，无法自动调整。", "自动调整", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            // 同步门型偏好和车辆高度到请求
            if (_autoAdjustmentRequest != null)
            {
                _autoAdjustmentRequest.RequireWidthLarger = _requireWidthLarger;
                _autoAdjustmentRequest.VehicleHeightModelUnits =
                    UnitsConverter.ConvertFromMeters(_vehicleHeightInMeters);
            }

            var oldCursor = System.Windows.Input.Mouse.OverrideCursor;
            try
            {
                System.Windows.Input.Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;

                ObjectPassageProjectionOptimizationResult result = _autoAdjustmentProvider != null
                    ? _autoAdjustmentProvider()
                    : ObjectPassageProjectionOptimizer.Optimize(_autoAdjustmentRequest);
                if (!result.Success)
                {
                    MessageBox.Show(result.ErrorMessage ?? "自动调整失败。", "自动调整", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                RotationXDegrees = NormalizeDisplayDegrees(result.Correction.XDegrees);
                RotationYDegrees = NormalizeDisplayDegrees(result.Correction.YDegrees);
                RotationZDegrees = NormalizeDisplayDegrees(result.Correction.ZDegrees);
                if (result.ComputedLiftOffsetModelUnits.HasValue)
                {
                    GroundPathLiftHeightInMeters = Math.Round(UnitsConverter.ConvertToMeters(result.ComputedLiftOffsetModelUnits.Value), 3);
                }
                if (result.AabbSx.HasValue)
                    AutoAdjustAabbSizes = (result.AabbSx.Value, result.AabbSy.Value, result.AabbSz.Value);
                LogManager.Debug(
                    $"[自动调整] 已写入角度: {RotationCorrection}, " +
                    $"截面宽度={result.Score.WidthAcrossPath:F3}, 高度={result.Score.HeightAlongHostUp:F3}, 面积={result.Score.Area:F3}");
            }
            finally
            {
                System.Windows.Input.Mouse.OverrideCursor = oldCursor;
            }
        }

        private void OnAlignToGroundClick(object sender, RoutedEventArgs e)
        {
            LogManager.Info($"[贴合地面] 按钮被点击, provider={_alignToGroundProvider != null}");
            if (_alignToGroundProvider == null)
            {
                MessageBox.Show("当前无法使用贴合地面功能。", "贴合地面", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            _alignToGroundRequested = true;
            TryCommitInputValues();
            _adjustmentRequest = ObjectStartPlacementRequest.CreateTranslationOnly(GroundPathLiftHeightInMeters);
            DialogResult = false;
            Close();
        }

        private void OnQuickAngleClick(object sender, RoutedEventArgs e)
        {
            if (sender is Button button)
            {
                LogManager.Debug($"[快捷角度] 点击按钮: {button.Content}, Tag类型: {button.Tag?.GetType()}, Tag值: {button.Tag}");

                if (button.Tag != null)
                {
                    double? parsedAngle = null;
                    if (button.Tag is int intTag)
                    {
                        parsedAngle = intTag;
                    }
                    else if (button.Tag is string stringTag && double.TryParse(stringTag, out double angle))
                    {
                        parsedAngle = angle;
                    }
                    else if (button.Tag is double doubleTag)
                    {
                        parsedAngle = doubleTag;
                    }

                    if (parsedAngle.HasValue)
                    {
                        ApplyQuickAngle(parsedAngle.Value);
                        LogManager.Debug($"[快捷角度] 设置 {_activeAxisTarget} 轴角度为: {parsedAngle.Value}°");
                    }
                }
            }
        }

        private void OnAxisTextBoxGotFocus(object sender, RoutedEventArgs e)
        {
            if (ReferenceEquals(sender, XAxisTextBox))
            {
                _activeAxisTarget = RotationAxisTarget.X;
                return;
            }

            if (ReferenceEquals(sender, YAxisTextBox))
            {
                _activeAxisTarget = RotationAxisTarget.Y;
                return;
            }

            _activeAxisTarget = RotationAxisTarget.Z;
        }

        private void OnResetClick(object sender, RoutedEventArgs e)
        {
            RotationXDegrees = 0.0;
            RotationYDegrees = 0.0;
            RotationZDegrees = 0.0;
        }

        private void OnConfirmClick(object sender, RoutedEventArgs e)
        {
            if (!TryCommitInputValues())
            {
                return;
            }

            _adjustmentRequest = ObjectStartPlacementRequest.CreateRotationCorrection(RotationCorrection, GroundPathLiftHeightInMeters);
            DialogResult = true;
            Close();
        }

        private void OnTranslateClick(object sender, RoutedEventArgs e)
        {
            if (!TryCommitInputValues())
            {
                return;
            }

            _adjustmentRequest = ObjectStartPlacementRequest.CreateTranslationOnly(GroundPathLiftHeightInMeters);
            DialogResult = true;
            Close();
        }

        private void OnCancelClick(object sender, RoutedEventArgs e)
        {
            DialogResult = false;
            Close();
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private void ApplyQuickAngle(double angle)
        {
            switch (_activeAxisTarget)
            {
                case RotationAxisTarget.X:
                    RotationXDegrees = angle;
                    break;
                case RotationAxisTarget.Y:
                    RotationYDegrees = angle;
                    break;
                case RotationAxisTarget.Z:
                default:
                    RotationZDegrees = angle;
                    break;
            }
        }

        private bool TryCommitInputValues()
        {
            if (!TryUpdateNumberTextBox(XAxisTextBox, "请输入有效的 X 轴角度。"))
            {
                return false;
            }

            if (!TryUpdateNumberTextBox(YAxisTextBox, "请输入有效的 Y 轴角度。"))
            {
                return false;
            }

            if (!TryUpdateNumberTextBox(ZAxisTextBox, "请输入有效的 Z 轴角度。"))
            {
                return false;
            }

            if (!TryUpdateNumberTextBox(GroundLiftTextBox, "请输入有效的上下偏移值。"))
            {
                return false;
            }

            if (!TryUpdateNumberTextBox(VehicleHeightTextBox, "请输入有效的物流车高度。"))
            {
                return false;
            }

            if (VehicleHeightInMeters < 0.0)
            {
                ShowInputError("物流车高度必须大于或等于 0。", VehicleHeightTextBox);
                return false;
            }

            return true;
        }

        private static bool TryUpdateNumberTextBox(TextBox textBox, string message)
        {
            BindingExpression binding = textBox.GetBindingExpression(TextBox.TextProperty);

            if (EditableNumberConverter.IsIntermediateText(textBox.Text))
            {
                ShowInputError(message, textBox);
                return false;
            }

            if (!EditableNumberConverter.TryParseNumber(textBox.Text.Trim(), System.Globalization.CultureInfo.CurrentCulture, typeof(double), out _))
            {
                ShowInputError(message, textBox);
                return false;
            }

            try
            {
                binding?.UpdateSource();
            }
            catch (Exception)
            {
                ShowInputError(message, textBox);
                return false;
            }

            if (Validation.GetHasError(textBox))
            {
                ShowInputError(message, textBox);
                return false;
            }

            return true;
        }

        private static void ShowInputError(string message, TextBox textBox)
        {
            MessageBox.Show(message, "输入错误", MessageBoxButton.OK, MessageBoxImage.Warning);
            textBox.Focus();
            textBox.SelectAll();
        }

        private static double NormalizeDisplayDegrees(double degrees)
        {
            double normalized = degrees % 360.0;
            if (normalized < 0.0)
            {
                normalized += 360.0;
            }

            return Math.Abs(normalized) < 1e-9 ? 0.0 : normalized;
        }
    }
}
