using System.Reflection;
using System.Text;
using Cassandra;
using System.ComponentModel.DataAnnotations;
using JiShe.CollectBus.Common.Attributes;
using Volo.Abp.Data;

namespace JiShe.CollectBus.Cassandra.Extensions
{
    public static class SessionExtension
    {
        public static void CreateTable<TEntity>(this ISession session,string? defaultKeyspace=null) where TEntity : class
        {
            var type = typeof(TEntity);
            var tableAttribute = type.GetCustomAttribute<CassandraTableAttribute>();
            var tableName = tableAttribute?.Name ?? type.Name.ToLower();
            var tableKeyspace = session.Keyspace;

            var properties = type.GetProperties();

            // 分区键设置
            var primaryKey = properties.FirstOrDefault(p => p.GetCustomAttribute<PartitionKeyAttribute>() != null);

            if (primaryKey == null)
            {
                throw new InvalidOperationException($"No primary key defined for type {type.Name}");
            }

            // 集群键设置
            var clusteringKeys = properties.Where(p => p.GetCustomAttribute<ClusteringKeyAttribute>() != null).Select(a=>a.Name).ToList();
            var clusteringKeyCql = string.Empty;
            if (clusteringKeys.Any())
            {
                clusteringKeyCql = $", {string.Join(", ", clusteringKeys)}";
            }

            var cql = new StringBuilder();
            cql.Append($"CREATE TABLE IF NOT EXISTS {tableKeyspace}.{tableName} (");

            foreach (var prop in properties)
            {
                var ignoreAttribute = prop.GetCustomAttribute<CassandraIgnoreAttribute>();
                if (ignoreAttribute != null) continue;
                var columnName = prop.Name.ToLower();
                var cqlType = GetCassandraType(prop.PropertyType);

                cql.Append($"{columnName} {cqlType}, ");
            }
            cql.Length -= 2; // Remove last comma and space
            cql.Append($", PRIMARY KEY (({primaryKey.Name.ToLower()}){clusteringKeyCql}))");

            session.Execute(cql.ToString());
        }

        private static string GetCassandraType(Type type)
        {
            // 基础类型处理
            switch (Type.GetTypeCode(type))
            {
                case TypeCode.String: return "text";
                case TypeCode.Int32: return "int";
                case TypeCode.Int64: return "bigint";
                case TypeCode.Boolean: return "boolean";
                case TypeCode.DateTime: return "timestamp";
                case TypeCode.Byte: return "tinyint";
            }

            if (type == typeof(Guid)) return "uuid";
            if (type == typeof(DateTimeOffset)) return "timestamp";
            if (type == typeof(Byte[])) return "blob";
            if (type == typeof(ExtraPropertyDictionary)) return "map<text,text>";

            // 处理集合类型
            if (type.IsGenericType)
            {
                var genericType = type.GetGenericTypeDefinition();
                var elementType = type.GetGenericArguments()[0];

                if (genericType == typeof(List<>))
                    return $"list<{GetCassandraType(elementType)}>";
                if (genericType == typeof(HashSet<>))
                    return $"set<{GetCassandraType(elementType)}>";
                if (genericType == typeof(Nullable<>))
                    return GetCassandraType(elementType);
                if (genericType == typeof(Dictionary<,>))
                {
                    var keyType = type.GetGenericArguments()[0];
                    var valueType = type.GetGenericArguments()[1];
                    return $"map<{GetCassandraType(keyType)}, {GetCassandraType(valueType)}>";
                }
            }

            throw new NotSupportedException($"不支持的类型: {type.Name}");
        }


    }
}
