using Newtonsoft.Json;
using PropertyChanged;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BDU.Models
{
    [AddINotifyPropertyChangedInterface]
    public class ParameterModel
    {

        #region 构造函数

        public ParameterModel()
        {

        }

        public ParameterModel(ParameterModel source)
        {
            if (source == null) return;

            ID = source.ID;
            Name = source.Name;
            Type = source.Type;
            Category = source.Category;
            IsUseVar = source.IsUseVar;
            IsSave = source.IsSave;
            VariableName = source.VariableName;
            VariableID = source.VariableID;
            IsGlobal = source.IsGlobal;
            Value = source.Value;
            LowerLimit = source.LowerLimit;
            UpperLimit = source.UpperLimit;
            IsOutputToReport = source.IsOutputToReport;
        }

        #endregion

        public Guid ID { get; set; } = Guid.NewGuid();

        public bool IsVisible { get; set; } = true;

        public string Name { get; set; }

        public Type? Type { get; set; } = typeof(string);

        public ParameterCategory Category { get; set; } = ParameterCategory.Temp;

        public bool IsGlobal { get; set; }

        public object? Value { get; set; }

        public object? LowerLimit { get; set; }

        public object? UpperLimit { get; set; }

        public bool Result { get; set; } = true;

        public bool IsUseVar { get; set; }

        public bool IsSave { get; set; }

        public string? VariableName { get; set; }

        public Guid? VariableID { get; set; }
        
        /// <summary>
        /// 是否输出到报告（仅对输出参数有效，默认为false）
        /// </summary>
        public bool IsOutputToReport { get; set; } = false;

        public enum ParameterCategory
        {
            Input,
            Output,
            Temp
        }

        public object? GetActualValue(Dictionary<Guid, ParameterModel> paraList)
        {
            // 用于检测循环引用的哈希集合
            HashSet<Guid> visitedIds = [];
            ParameterModel current = this;

            while (current != null)
            {
                // 如果没有使用变量，则返回值
                if (!current.IsUseVar)
                {
                    return current.Value;
                }

                // 检测循环引用
                if (visitedIds.Contains(current.ID))
                {
                    return null;
                }
                visitedIds.Add(current.ID);

                // 如果当前参数没有关联变量，则返回其实际值
                if (current.VariableID == null)
                {
                    if (Type != null && Value != null)
                    {
                        try
                        {
                            return Convert.ChangeType(Value, Type);
                        }
                        catch
                        {
                            return Value;
                        }
                    }
                }

                // 查找下一个关联参数
                ParameterModel? next = paraList[(Guid)current.VariableID!];
                if (next == null)
                {
                    return null;
                }

                current = next;
            }

            return null;
        }

        /// <summary>
        /// 获取方法步骤中的返回值映射的主程序参数
        /// </summary>
        /// <param name="paraList"></param>
        /// <returns></returns>
        public ParameterModel? GetCurrentParameter(Dictionary<Guid, ParameterModel> paraList)
        {
            // 用于检测循环引用的哈希集合
            HashSet<Guid> visitedIds = new HashSet<Guid>();
            ParameterModel current = this;

            while (current != null)
            {
                // 如果没有使用变量，则返回值
                if (current.VariableID == null)
                {
                    return current;
                }

                // 检测循环引用
                if (visitedIds.Contains(current.ID))
                {
                    return null;
                }
                visitedIds.Add(current.ID);

                // 如果当前参数没有关联变量，则返回其实际值
                if (current.VariableID == null)
                {
                    if (Type != null && Value != null)
                    {
                        try
                        {
                            return current;
                        }
                        catch
                        {
                            return null;
                        }
                    }
                }

                // 查找下一个关联参数
                ParameterModel? next = paraList[(Guid)current.VariableID!];
                if (next == null)
                {
                    return null;
                }

                current = next;
            }

            return null;
        }

        public (bool, string?) GetResult()
        {

            if (Type == typeof(string) && (!string.IsNullOrWhiteSpace(LowerLimit?.ToString()) || !string.IsNullOrWhiteSpace(UpperLimit?.ToString())))
            {
                return (true, $"参数 [ {Name}({Type}) ] 不可比较");
            }

            // 当值或限制条件不存在时返回true
            if (Value == null || (LowerLimit == null && UpperLimit == null))
            {
                return (true, null);
            }

            // 检查空字符串情况
            if (string.IsNullOrWhiteSpace(Value?.ToString()) || (string.IsNullOrWhiteSpace(LowerLimit?.ToString()) && string.IsNullOrWhiteSpace(UpperLimit?.ToString())))
            {
                return (true, null);
            }

            // 尝试将值转换为可比较的类型
            try
            {
                object? comparableValue = ConvertToComparable(Value);
                object? comparableLower = LowerLimit != null ? ConvertToComparable(LowerLimit) : null;
                object? comparableUpper = UpperLimit != null ? ConvertToComparable(UpperLimit) : null;

                if (comparableValue == null)
                {
                    return (true, $"参数 [ {Name}({Type}) ] 不可比较");
                }

                bool lowerValid = true;
                bool upperValid = true;

                // 处理下限比较
                if (comparableLower != null)
                {
                    lowerValid = CompareValues(comparableValue, comparableLower) >= 0;
                }

                // 处理上限比较
                if (comparableUpper != null)
                {
                    upperValid = CompareValues(comparableValue, comparableUpper) <= 0;
                }

                return (lowerValid && upperValid, null);
            }
            catch (Exception ex)
            {
                return (true, $"参数 [ {Name}({Type}) ] 上下限比较失败:{ex.Message}");
            }
        }

        private static object? ConvertToComparable(object value)
        {
            if (value is IConvertible convertible)
            {
                // 尝试转换为最适合比较的类型
                try
                {
                    return convertible.ToDouble(null);
                }
                catch
                {

                }
                try
                {
                    return convertible.ToDateTime(null);
                }
                catch
                {

                }
            }

            return null;
        }

        private static int CompareValues(object a, object b)
        {
            // 优先尝试数值比较
            if (a is double aDouble && b is double bDouble)
            {
                return aDouble.CompareTo(bDouble);
            }

            // 尝试日期比较
            if (a is DateTime aDate && b is DateTime bDate)
            {
                return aDate.CompareTo(bDate);
            }

            return 0;
        }
    }
}
