using JLHHJSvr.Com.Model;
using JLHHJSvr.LJException;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;

namespace JLHHJSvr.Tools
{
    public class AutoInit
    {
        private static readonly ConcurrentDictionary<string, CacheItem> ColumnInfoCache = new ConcurrentDictionary<string, CacheItem>();
        private static readonly TimeSpan CacheExpirationTime = TimeSpan.FromMinutes(60); // 缓存过期时间1小时


        public static void AutoInitS <T>(SqlCommand cmd, T instance){
            var tableName = instance.GetType().Name;
            var currentTime = DateTime.Now;

            if (ColumnInfoCache.TryGetValue(tableName, out var cache) && currentTime - cache.CacheTime < CacheExpirationTime)
            {
                // 缓存有效，使用缓存
                foreach (var item in cache.ColumnInfo)
                {
                    var column = item.Value.Column;
                    var isNullable = item.Value.IsNullable;

                    var property = instance.GetType().GetProperties().FirstOrDefault(prop => prop.Name.Equals(column, StringComparison.OrdinalIgnoreCase));
                    if (property == null) continue;

                    if (isNullable.Equals("NO") && property.GetValue(instance) == null)
                    {
                        var type = property.PropertyType;

                        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
                        {
                            type = type.GetGenericArguments()[0];
                        }

                        if (type.IsAssignableFrom(typeof(string)))
                        {
                            property.SetValue(instance, "");
                        }
                        else if (type.IsAssignableFrom(typeof(int))
                            || type.IsAssignableFrom(typeof(decimal))
                            || type.IsAssignableFrom(typeof(byte)))
                        {
                            property.SetValue(instance, Activator.CreateInstance(type));
                        }
                    }
                }
            } else
            {
                // 缓存过期，重新加载列信息
                var columnInfo = new Dictionary<string, ColumnItem>();
                cmd.CommandText = @"SELECT COLUMN_NAME, IS_NULLABLE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName";
                cmd.Parameters.Clear();
                cmd.Parameters.AddWithValue("@tableName", instance.GetType().Name);
                using (var reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        var column = Convert.ToString(reader["COLUMN_NAME"]).Trim();
                        var isNullable = Convert.ToString(reader["IS_NULLABLE"]).Trim();
                        columnInfo[column] = new ColumnItem(column, isNullable);
                    }
                }
                ColumnInfoCache[tableName] = new CacheItem { CacheTime = currentTime, ColumnInfo = columnInfo };
                // 使用新的列信息初始化属性
                foreach (var item in columnInfo)
                {
                    var column = item.Value.Column;
                    var isNullable = item.Value.IsNullable;

                    var property = instance.GetType().GetProperties().FirstOrDefault(prop => prop.Name.Equals(column, StringComparison.OrdinalIgnoreCase));
                    if (property == null) continue;
                    if (isNullable.Equals("NO") && property.GetValue(instance) == null)
                    {
                        var type = property.PropertyType;

                        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
                        {
                            type = type.GetGenericArguments()[0];
                        }

                        if (type.IsAssignableFrom(typeof(string)))
                        {
                            property.SetValue(instance, "");
                        }
                        else if (type.IsAssignableFrom(typeof(int))
                            || type.IsAssignableFrom(typeof(decimal))
                            || type.IsAssignableFrom(typeof(byte)))
                        {
                            property.SetValue(instance, Activator.CreateInstance(type));
                        }
                    }
                }
            }
        }

        public static void AutoInitS<T>(T instance)
        {
            foreach (var TB in instance.GetType().GetProperties())
            {
                var type = TB.PropertyType;

                var value = TB.GetValue(instance, null);
                if (value == null)
                {
                    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
                    {
                        type = type.GetGenericArguments()[0];
                    }

                    if (type.IsAssignableFrom(typeof(string)))
                    {
                        value = string.Empty;
                    }
                    else if (type.IsAssignableFrom(typeof(int))
                        || type.IsAssignableFrom(typeof(decimal))
                        || type.IsAssignableFrom(typeof(byte)))
                    {
                        value = Activator.CreateInstance(type);
                    }

                    if (value != null)
                    {
                        TB.SetValue(instance, value, null);
                    }
                }
            }
        }
    }
}
