using Common.Models;
using Microsoft.Win32;
using Newtonsoft;
using Newtonsoft.Json;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows;
using System.Windows.Media;
using System.Xml.Serialization;

namespace Common
{
    public class File_Operator
    {
        private static readonly object _lock = new object();

        public static T Xml_Serialize<T>(string strFile, bool bSave, T param, out bool bReadOK) where T : class
        {
            lock (_lock)
            {
                bReadOK = true;
                XmlSerializer xs = null;

                // 针对 BaseBottleBox 集合，显式指定所有派生类
                if (typeof(T) == typeof(ProjectProperty))
                {
                    Type[] extraTypes = new Type[]
                    {
                       typeof(BaseBottleBox),
                       typeof(SampleBottleBoxModel),
                       typeof(SourceLiquidBottleBoxModel),
                       typeof(SourcePowderBottleBoxModel),
                       typeof(SourcePowderBottleBoxModel_125ml),
                       typeof(TipBoxModel),
                       typeof(SourcePowderBottleModel),
                       typeof(TipHeadItem)
                    };
                    xs = new XmlSerializer(typeof(ProjectProperty), extraTypes);
                }
                else
                {
                    xs = new XmlSerializer(param.GetType());
                }

                try
                {
                    // 使用 using 自动释放流（避免资源泄漏）
                    if (bSave)
                    {
                        using (Stream stream = new FileStream(strFile, FileMode.Create, FileAccess.Write, FileShare.Read))
                        {
                            xs.Serialize(stream, param);
                        }
                    }
                    else
                    {
                        if (File.Exists(strFile))
                        {
                            using (Stream stream = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.Read))
                            {
                                param = xs.Deserialize(stream) as T;
                            }
                            return param;
                        }
                        else
                        {
                            // 文件不存在时，先创建并序列化默认值
                            using (Stream stream = new FileStream(strFile, FileMode.Create, FileAccess.Write, FileShare.Read))
                            {
                                xs.Serialize(stream, param);
                            }
                            // 重新读取
                            using (Stream stream = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.Read))
                            {
                                param = xs.Deserialize(stream) as T;
                            }
                            return param;
                        }
                    }
                }
                catch (Exception ex)
                {
                    bReadOK = false;
                    MessageBox.Show($"序列化失败：{ex.Message}\n{ex.StackTrace}", "错误");
                }
                return null;
            }
        }


        /// <summary>
        /// XML文件读写
        /// 保存配置参数  bReadOK==false为发生异常
        /// </summary>
        /// <typeparam name="T">类类型</typeparam>
        /// <param name="strFile">完整文件路径名</param>
        /// <param name="bSave">true:保存；false:读取</param>
        /// <param name="param">要进行序列化或反序列化的对象实例</param>
        /// <param name="bReadOK">是否读写成功，有异常</param>
        /// <returns>读取的数据</returns>
        //public static T Xml_Serialize<T>(string strFile, bool bSave, T param, out bool bReadOK) where T : class
        //{
        //    lock (_lock)
        //    {
        //        bReadOK = true;
        //        XmlSerializer xs = new XmlSerializer(param.GetType());
        //        try
        //        {
        //            if (bSave)
        //            {
        //                //创建一个 FileStream 对象，以 FileMode.Create 模式打开文件，用于写入数据。
        //                //使用 xs.Serialize 方法将 param 对象序列化为 XML 数据，并写入文件。
        //                //关闭文件流。
        //                Stream stream = new FileStream(strFile, FileMode.Create, FileAccess.Write, FileShare.Read);
        //                xs.Serialize(stream, param);
        //                stream.Close();
        //            }
        //            else
        //            {
        //                //检查文件是否存在。
        //                //如果文件存在，创建一个 FileStream 对象，以 FileMode.Open 模式打开文件，用于读取数据。
        //                //使用 xs.Deserialize 方法将文件中的 XML 数据反序列化为 T 类型的对象，并赋值给 param。
        //                //关闭文件流，并返回反序列化后的对象。

        //                if (File.Exists(strFile))
        //                {
        //                    Stream stream = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.Read);
        //                    param = xs.Deserialize(stream) as T;
        //                    stream.Close();
        //                    return param;
        //                }
        //                else
        //                {
        //                    //如果文件不存在，先创建一个 FileStream 对象，以 FileMode.Create 模式打开文件，将 param 对象序列化为 XML 数据并写入文件。
        //                    //再次打开文件，读取其中的 XML 数据进行反序列化，并返回反序列化后的对象。
        //                    Stream stream = new FileStream(strFile, FileMode.Create, FileAccess.Write, FileShare.Read);
        //                    xs.Serialize(stream, param);
        //                    stream.Close();

        //                    stream = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.Read);
        //                    param = xs.Deserialize(stream) as T;
        //                    stream.Close();
        //                    return param;
        //                }
        //            }
        //        }
        //        catch (Exception ex)
        //        {
        //            bReadOK = false;
        //            MessageBox.Show(ex.Message);
        //        }
        //        return null;
        //    }
        //}

        /// <summary>
        /// 通过文件名寻找同目录下的其他同类型文件
        /// </summary>
        /// <param name="file">文件的绝对路径名</param>
        public static List<string> GetFile(string file)
        {
            List<string> listFile = new List<string>();
            if (!string.IsNullOrEmpty(file) && File.Exists(file))
            {
                int index = file.LastIndexOf("\\");
                if (-1 == index) return null;
                string path = file.Substring(0, index);//文件所在文件夹路径
                string name = file.Substring(index);//文件名
                string postfix = "";//取出后缀名
                if (name.Contains("."))
                {
                    postfix = name.Substring(name.LastIndexOf('.'));//例： .txt
                }
                else
                {
                    return null;
                }
                string[] files = null;
                try
                {
                    files = Directory.GetFiles(path);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    return null;
                }
                foreach (var item in files)
                {
                    int nIndex = item.IndexOf(postfix);
                    if (nIndex != -1)
                    {
                        listFile.Add(item);
                    }
                }
            }
            return listFile;
        }


        #region 对注册表进行读写
        //public static void CreatRegistryPath(string strPathName)
        //{
        //    try
        //    {
        //        RegistryKey key = Registry.LocalMachine;
        //        //RegistryKey software = key.CreateSubKey("software\\test");
        //        RegistryKey software = key.CreateSubKey("software\\" + strPathName);
        //        key.Close();
        //    }
        //    catch (Exception ex)
        //    {
        //        MessageBox.Show("对注册表创建路径时出现异常!" + ex.Message);
        //    }
        //}

        //public static void DeleteRegistryPath(string strPathName)
        //{
        //    try
        //    {
        //        RegistryKey key = Registry.LocalMachine;
        //        //key.DeleteSubKey("software\\test", true);
        //        key.DeleteSubKey("software\\" + strPathName, true);
        //        key.Close();
        //    }
        //    catch (Exception ex)
        //    {
        //        MessageBox.Show("对注册表删除路径时出现异常!" + ex.Message);
        //    }
        //}

        //public static void SetRegistryValue(string strPathName, string strKey, string strValue)
        //{
        //    try
        //    {
        //        RegistryKey key = Registry.LocalMachine;
        //        RegistryKey software = key.OpenSubKey("software\\" + strPathName, true);
        //        //software.SetValue("test", "博客园");
        //        software.SetValue(strKey, strValue);
        //        key.Close();
        //    }
        //    catch (Exception ex)
        //    {
        //        MessageBox.Show("对注册表设置键值时出现异常!" + ex.Message);
        //    }
        //}

        //public static string GetRegistryValue(string strPathName, string strKey)
        //{
        //    try
        //    {
        //        RegistryKey Key = Registry.LocalMachine;
        //        RegistryKey myreg = Key.OpenSubKey("software\\" + strPathName, true);
        //        //info = myreg.GetValue("test").ToString();
        //        string strValue = myreg.GetValue(strKey).ToString();
        //        myreg.Close();
        //        return strValue;
        //    }
        //    catch (Exception ex)
        //    {
        //        MessageBox.Show("对注册表获取值时出现异常!" + ex.Message);
        //        return "";
        //    }
        //}

        //public static void DeleteRegistryKey(string strPathName, string strKey)
        //{
        //    try
        //    {
        //        RegistryKey delKey = Registry.LocalMachine.OpenSubKey("Software\\" + strPathName, true);
        //        //delKey.DeleteValue("test");
        //        delKey.DeleteValue(strKey);
        //        delKey.Close();
        //    }
        //    catch (Exception ex)
        //    {
        //        MessageBox.Show("对注册表删除键值时出现异常!" + ex.Message);
        //    }
        //}
        #endregion



        #region 深度拷贝
        public static T DeepCopy<T>(T obj)
        {
            if (obj == null) return default;
            //var json = JsonConvert.SerializeObject(obj);
            //return JsonConvert.DeserializeObject<T>(json);

            var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
            string json = JsonConvert.SerializeObject(obj, settings);
            return JsonConvert.DeserializeObject<T>(json, settings);
        }

        [Obsolete("弃用，使用上面的DeepCopy方法")]
        public static T DeepCopy_1<T>(T obj)
        {
            if (obj == null) return default;

            Type actualType = obj.GetType();

            // 处理值类型和字符串
            // 处理值类型和字符串
            if (actualType.IsValueType || actualType == typeof(string))
                return obj;

            // 处理数组
            if (actualType.IsArray)
            {
                var elementType = typeof(T).GetElementType();
                var sourceArray = (Array)(object)obj;
                var copiedArray = Array.CreateInstance(elementType, sourceArray.Length);
                for (int i = 0; i < sourceArray.Length; i++)
                {
                    copiedArray.SetValue(DeepCopy((dynamic)sourceArray.GetValue(i)), i);
                }
                return (T)(object)copiedArray;
            }

            // 处理集合（如 List, ObservableCollection）
            // 处理集合（优先直接创建目标类型，避免冗余转换）
            if (typeof(IEnumerable).IsAssignableFrom(actualType) && actualType != typeof(string))
            {
                return DeepCopyCollection<T>(obj);
            }

            // 处理普通对象（核心修改）
            // 关键修改2：按“实际类型”创建实例（而非 T 的声明类型）
            object copy = Activator.CreateInstance(actualType);
            // 关键修改3：拷贝所有字段（包括私有字段+派生类特有字段）
            FieldInfo[] fields = actualType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

            foreach (var field in fields)
            {
                if (field.IsStatic) continue; // 跳过静态字段

                var value = field.GetValue(obj);
                // 递归深拷贝字段值（保持原逻辑）
                var copiedValue = DeepCopy((dynamic)value);
                field.SetValue(copy, copiedValue);
            }

            // 强制转换为 T（因为实际类型是 T 的派生类，转换安全）
            return (T)copy;
        }


        /// <summary>
        /// 专门处理 ObservableCollection 类型属性（支持只读属性）
        /// </summary>
        private static void DeepCopyObservableCollectionProperty(PropertyInfo property, object sourceObj, object targetObj)
        {
            // 获取源集合和元素类型
            var sourceCollection = property.GetValue(sourceObj) as IEnumerable;
            var elementType = property.PropertyType.GetGenericArguments()[0];

            // 创建新的 ObservableCollection 实例（匹配原属性类型）
            var targetCollection = Activator.CreateInstance(property.PropertyType) as IList;
            if (targetCollection == null)
                throw new InvalidOperationException($"无法创建 {property.PropertyType.Name} 实例");

            // 深拷贝集合元素并添加到新集合
            foreach (var item in sourceCollection)
            {
                var copiedItem = DeepCopy((dynamic)item);
                targetCollection.Add(copiedItem);
            }

            // 给目标对象赋值：可写属性直接 SetValue，只读属性通过底层字段赋值
            if (property.CanWrite)
            {
                property.SetValue(targetObj, targetCollection);
            }
            else
            {
                // 匹配只读属性的底层字段（常见命名规范：_propertyName 或 m_propertyName）
                var fieldName = $"_{char.ToLower(property.Name[0])}{property.Name.Substring(1)}";
                var field = targetObj.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);

                // 若未匹配到，尝试 mPropertyName 规范
                if (field == null)
                {
                    fieldName = $"m{property.Name}";
                    field = targetObj.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
                }

                if (field != null && field.FieldType == property.PropertyType)
                {
                    field.SetValue(targetObj, targetCollection);
                }
                else
                {
                    throw new InvalidOperationException($"无法给只读属性 {property.DeclaringType.Name}.{property.Name} 赋值，请检查字段命名（预期：{fieldName}）");
                }
            }
        }

        /// <summary>
        /// 优化集合深拷贝：直接创建目标类型集合，避免 List 中转
        /// </summary>
        private static T DeepCopyCollection<T>(T sourceCollection)
        {
            var sourceType = typeof(T);
            var elementType = sourceType.IsGenericType ? sourceType.GetGenericArguments()[0] : typeof(object);

            // 直接创建目标类型的集合实例（如 ObservableCollection<SampleBottleModel>）
            var targetCollection = Activator.CreateInstance(sourceType) as IList;
            if (targetCollection == null)
                throw new InvalidOperationException($"无法创建集合类型 {sourceType.Name} 实例");

            // 深拷贝每个元素并添加到新集合
            foreach (var item in (IEnumerable)sourceCollection)
            {
                var copiedItem = DeepCopy((dynamic)item);
                targetCollection.Add(copiedItem);
            }

            return (T)targetCollection;
        }

        public static ObservableCollection<T> DeepCopyObservableCollection<T>(ObservableCollection<T> source)
        {
            // 序列化为 JSON 字符串
            var json = JsonConvert.SerializeObject(source);
            // 从 JSON 字符串反序列化为新对象
            return JsonConvert.DeserializeObject<ObservableCollection<T>>(json);
        }

        #endregion
    }
}
