using System;
using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Threading.Tasks;
using Apache.IoTDB;
using Apache.IoTDB.DataStructure;
using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.Common.Helpers;
using JiShe.CollectBus.Common.Models;
using JiShe.CollectBus.IoTDB.Attribute;
using JiShe.CollectBus.IoTDB.Context;
using JiShe.CollectBus.IoTDB.Interface;
using JiShe.CollectBus.IoTDB.Model;
using JiShe.CollectBus.IoTDB.Options;
using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities;

namespace JiShe.CollectBus.IoTDB.Provider
{
    /// <summary>
    /// IoTDB数据源
    /// </summary>
    public class IoTDbProvider : IIoTDbProvider, ITransientDependency
    {
        private static readonly ConcurrentDictionary<Type, DeviceMetadata> MetadataCache = new();
        private readonly ILogger<IoTDbProvider> _logger;
        private readonly IIoTDbSessionFactory _sessionFactory;
        private readonly IoTDBRuntimeContext _runtimeContext;

        private IIoTDbSessionPool CurrentSession =>
        _sessionFactory.GetSessionPool(_runtimeContext.UseTableSessionPool);

        /// <summary>
        /// IoTDbProvider
        /// </summary>
        /// <param name="logger"></param>
        /// <param name="sessionFactory"></param>
        /// <param name="runtimeContext"></param>
        public IoTDbProvider(
            ILogger<IoTDbProvider> logger,
            IIoTDbSessionFactory sessionFactory,
            IoTDBRuntimeContext runtimeContext)
        {
            _logger = logger;
            _sessionFactory = sessionFactory;
            _runtimeContext = runtimeContext;

        }

        /// <summary>
        /// 插入数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task InsertAsync<T>(T entity) where T : IoTEntity
        {
            try
            {
                var metadata = await GetMetadata<T>();

                var tablet = BuildTablet(new[] { entity }, metadata);

                await CurrentSession.InsertAsync(tablet);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"{nameof(InsertAsync)} IoTDB插入{typeof(T).Name}的数据时发生异常");
                throw;
            }
        }

        /// <summary>
        /// 批量插入数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public async Task BatchInsertAsync<T>(IEnumerable<T> entities) where T : IoTEntity
        {
            try
            {
                var metadata = await GetMetadata<T>();

                var batchSize = 1000;
                var batches = entities.Chunk(batchSize);

                foreach (var batch in batches)
                {
                    var tablet = BuildTablet(batch, metadata);
                    await CurrentSession.InsertAsync(tablet);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"{nameof(BatchInsertAsync)} IoTDB批量插入{typeof(T).Name}的数据时发生异常");
                throw;
            }
        }

        /// <summary>
        /// 批量插入数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="deviceMetadata">设备元数据</param>
        /// <param name="entities"></param>
        /// <returns></returns>
        public async Task BatchInsertAsync<T>(DeviceMetadata deviceMetadata, IEnumerable<T> entities) where T : IoTEntity
        {
            try
            {

                var batchSize = 1000;
                var batches = entities.Chunk(batchSize);

                foreach (var batch in batches)
                {
                    var tablet = BuildTablet(batch, deviceMetadata);
                    await CurrentSession.InsertAsync(tablet);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"{nameof(BatchInsertAsync)} IoTDB批量插入{typeof(T).Name}的数据时发生异常");
                throw;
            }
        }


        /// <summary>
        /// 删除数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="options"></param>
        /// <returns></returns>
        public async Task<object> DeleteAsync<T>(IoTDBQueryOptions options) where T : IoTEntity
        {
            try
            {
                var query = await BuildDeleteSQL<T>(options);
                var result = await CurrentSession.ExecuteQueryStatementAsync(query);

                if (result == null)
                {
                    return 0;
                }

                if (!result.HasNext())
                {
                    _logger.LogWarning($"{typeof(T).Name} IoTDB删除{typeof(T).Name}的数据时，没有返回受影响记录数量。");
                    return 0;
                }

                //获取唯一结果行
                var row = result.Next();
                await result.Close();
                var dataResult = row.Values[0];
                return dataResult;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"{nameof(DeleteAsync)} IoTDB删除{typeof(T).Name}的数据时发生异常");
                throw;
            }
        }

        /// <summary>
        /// 获取设备元数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public async Task<DeviceMetadata> GetMetadata<T>() where T : IoTEntity
        {
            var columns = CollectColumnMetadata(typeof(T));
            var metadata = BuildDeviceMetadata<T>(columns);
            var metaData = MetadataCache.AddOrUpdate(
                typeof(T),
                addValueFactory: t => metadata, // 如果键不存在，用此值添加
                updateValueFactory: (t, existingValue) =>
                {
                    var columns = CollectColumnMetadata(t);
                    var metadata = BuildDeviceMetadata<T>(columns);

                    //对现有值 existingValue 进行修改，返回新值
                    existingValue.ColumnNames = metadata.ColumnNames;
                    return existingValue;
                }
            );

            return await Task.FromResult(metaData);
        }

        /// <summary>
        /// 查询数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="options"></param>
        /// <returns></returns>
        public async Task<BusPagedResult<T>> QueryAsync<T>(IoTDBQueryOptions options) where T : IoTEntity, new()
        {
            try
            {
                var stopwatch2 = Stopwatch.StartNew();

                var query = await BuildQuerySQL<T>(options);
                var sessionDataSet = await CurrentSession.ExecuteQueryStatementAsync(query);

                
                _logger.LogWarning($"{nameof(QueryAsync)} 主题的任务 {options.TableNameOrTreePath} 路径批次{options.PageIndex}任务数据读取完成，共消耗{stopwatch2.ElapsedMilliseconds}毫秒。");
                var result = new BusPagedResult<T>
                {
                    TotalCount = await GetTotalCount<T>(options),
                    Items = await ParseResults<T>(sessionDataSet, options.PageSize),
                    PageIndex = options.PageIndex,
                    PageSize = options.PageSize,

                };
                stopwatch2.Stop();
                _logger.LogWarning($"{nameof(QueryAsync)} 主题的任务 {options.TableNameOrTreePath} 路径批次{options.PageIndex}任务数据读取完成，共消耗{stopwatch2.ElapsedMilliseconds}毫秒。");
                //int totalPageCount = (int)Math.Ceiling((double)result.TotalCount / options.PageSize);

                if (result.Items.Count() < result.PageSize)
                {
                    result.HasNext = false;
                }
                else
                {
                    result.HasNext = true;
                }

                //result.HasNext = result.Items.Count() > 0 ? result.Items.Count() < result.PageSize : false;

                return result;
            }
            catch (Exception ex)
            {
                CurrentSession.Dispose();
                _logger.LogError(ex, $"{nameof(QueryAsync)} IoTDB查询{typeof(T).Name}的数据时发生异常");
                throw;
            }
        }

        /// <summary>
        /// 构建Tablet
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entities">表实体</param>
        /// <param name="metadata">设备元数据</param></param>
        /// <returns></returns>
        private Tablet BuildTablet<T>(IEnumerable<T> entities, DeviceMetadata metadata) where T : IoTEntity
        {
            var timestamps = new List<long>();
            var values = new List<List<object>>();
            var devicePaths = new HashSet<string>();
            List<string> tempColumnNames = new List<string>();
            tempColumnNames.AddRange(metadata.ColumnNames);

            var entityTypeAttribute = typeof(T).GetCustomAttribute<EntityTypeAttribute>();

            if (entityTypeAttribute == null)
            {
                throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 {nameof(T)}的EntityType 没有指定，属于异常情况，-101");
            }

            if (metadata.EntityType != entityTypeAttribute.EntityType)
            {
                throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 {nameof(T)}的EntityType 和{nameof(DeviceMetadata)}的 EntityType 不一致，属于异常情况，-102");
            }

            if (metadata.EntityType == Enums.EntityTypeEnum.TreeModel && _runtimeContext.UseTableSessionPool == true)
            {
                throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 tree模型不能使用table模型Session连接，属于异常情况，-103");
            }
            else if (metadata.EntityType == Enums.EntityTypeEnum.TableModel && _runtimeContext.UseTableSessionPool == false)
            {
                throw new ArgumentException($"{nameof(BuildTablet)} 构建存储结构{nameof(Tablet)}时 table模型不能使用tree模型Session连接，属于异常情况，-104");
            }

            string tableNameOrTreePath = string.Empty;
            var tableNameOrTreePathAttribute = typeof(T).GetCustomAttribute<TableNameOrTreePathAttribute>();
            if (tableNameOrTreePathAttribute != null)
            {
                tableNameOrTreePath = tableNameOrTreePathAttribute.TableNameOrTreePath;
            }

            foreach (var entity in entities)
            {
                timestamps.Add(entity.Timestamps);
                var rowValues = new List<object>();

                foreach (var measurement in tempColumnNames)
                {

                    PropertyInfo propertyInfo = typeof(T).GetProperty(measurement);
                    if (propertyInfo == null)
                    {
                        throw new Exception($"{nameof(BuildTablet)} 构建表模型{typeof(T).Name}时，没有找到{measurement}属性，属于异常情况，-101。");
                    }

                    var value = propertyInfo.GetValue(entity);
                    if (propertyInfo.IsDefined(typeof(SingleMeasuringAttribute), false) && metadata.IsSingleMeasuring == true)//表示当前对象是单测点模式
                    {
                        if (value != null)
                        {
                            Type tupleType = value.GetType();
                            Type[] tupleArgs = tupleType.GetGenericArguments();
                            Type item2Type = tupleArgs[1]; // T 的实际类型
                            var item1 = tupleType.GetProperty("Item1")!.GetValue(value);
                            var item2 = tupleType.GetProperty("Item2")!.GetValue(value);
                            if (item1 == null || item2 == null)
                            {
                                throw new Exception($"{nameof(BuildTablet)} 构建表模型{typeof(T).Name}时，单测点模式构建失败，没有获取测点名称或者测点值，-102。");
                            }

                            var indexOf = metadata.ColumnNames.IndexOf(measurement);
                            metadata.ColumnNames[indexOf] = (string)item1!;

                            rowValues.Add(item2);
                        }
                        else
                        {
                            rowValues.Add(null);
                        }

                        //同时如果是单测点模式，且是table模型存储，路径只能通过DevicePathBuilder.GetDeviceTableName(entity)获取
                        if (_runtimeContext.UseTableSessionPool)
                        {
                            tableNameOrTreePath = DevicePathBuilder.GetDeviceTableName(entity);
                        }
                    }
                    else
                    {

                        //需要根据value的类型，进行相应的值映射转换，例如datetime转换为long的时间戳值
                        if (value != null)
                        {
                            Type tupleType = value.GetType();
                            var tempValue = tupleType.Name.ToUpper() switch
                            {
                                "DATETIME" => Convert.ToDateTime(value).GetDateTimeOffset().ToUnixTimeNanoseconds(),
                                _ => value
                            };

                            rowValues.Add(tempValue);
                        }
                        else
                        {
                            rowValues.Add(value);
                        }

                    }

                }

                values.Add(rowValues);

                //如果指定了路径
                if (!string.IsNullOrWhiteSpace(tableNameOrTreePath))
                {
                    devicePaths.Add(tableNameOrTreePath);
                }
                else
                {
                    if (!_runtimeContext.UseTableSessionPool)//树模型
                    {
                        devicePaths.Add(DevicePathBuilder.GetDevicePath(entity));
                    }
                    else
                    {
                        devicePaths.Add(DevicePathBuilder.GetTableName<T>());
                    }
                }
            }

            if (devicePaths.Count > 1)
            {
                throw new Exception($"{nameof(BuildTablet)} 构建Tablet《{typeof(T).Name}》时，批量插入的设备路径不一致。");
            }

            return _runtimeContext.UseTableSessionPool
                ? BuildTableSessionTablet(metadata, devicePaths.First(), values, timestamps)
                : BuildSessionTablet(metadata, devicePaths.First(), values, timestamps);
        }

        /// <summary>
        /// 构建tree模型的Tablet
        /// </summary>
        /// <param name="metadata">已解析的设备数据元数据</param>
        /// <param name="devicePath">设备路径</param>
        /// <param name="values">数据集合</param>
        /// <param name="timestamps">时间戳集合</param>
        /// <returns></returns>
        private Tablet BuildSessionTablet(DeviceMetadata metadata, string devicePath, List<List<object>> values, List<long> timestamps)
        {
            //todo 树模型需要去掉TAG类型和ATTRIBUTE类型的字段，只需要保留FIELD类型字段即可

            return new Tablet(
                devicePath,
                metadata.ColumnNames,
                metadata.DataTypes,
                values,
                timestamps
            );
        }

        /// <summary>
        /// 构建表模型的Tablet
        /// </summary>
        /// <param name="metadata">已解析的设备数据元数据</param>
        /// <param name="tableName">表名称</param>
        /// <param name="values">数据集合</param>
        /// <param name="timestamps">时间戳集合</param>
        /// <returns></returns>
        private Tablet BuildTableSessionTablet(DeviceMetadata metadata, string tableName, List<List<object>> values, List<long> timestamps)
        {
            var tablet = new Tablet(
                tableName,
                metadata.ColumnNames,
                metadata.ColumnCategories,
                metadata.DataTypes,
                values,
                timestamps
            );

            return tablet;
        }

        /// <summary>
        /// 构建查询语句
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="options"></param>
        /// <returns></returns>
        private async Task<string> BuildQuerySQL<T>(IoTDBQueryOptions options) where T : IoTEntity
        {
            var metadata = await GetMetadata<T>();
            var sb = new StringBuilder("SELECT TIME as Timestamps,");
            sb.AppendJoin(", ", metadata.ColumnNames);
            sb.Append($" FROM {options.TableNameOrTreePath}");

            if (options.Conditions.Any())
            {
                sb.Append(" WHERE ");
                sb.AppendJoin(" AND ", options.Conditions.Select(TranslateCondition));
            }

            sb.Append($" LIMIT {options.PageSize} OFFSET {options.PageIndex * options.PageSize}");
            return sb.ToString();
        }

        /// <summary>
        /// 构建删除语句
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="options"></param>
        /// <returns></returns>
        private async Task<string> BuildDeleteSQL<T>(IoTDBQueryOptions options) where T : IoTEntity
        {
            var metadata = await GetMetadata<T>();
            var sb = new StringBuilder();

            if (!_runtimeContext.UseTableSessionPool)
            {
                sb.Append("DELETE ");
            }
            else
            {
                sb.Append("DROP ");
            }

            sb.Append($" FROM {options.TableNameOrTreePath}");

            sb.AppendJoin(", ", metadata.ColumnNames);

            if (options.Conditions.Any())
            {
                sb.Append(" WHERE ");
                sb.AppendJoin(" AND ", options.Conditions.Select(TranslateCondition));
            }

            return sb.ToString();
        }

        /// <summary>
        /// 将查询条件转换为SQL语句
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException"></exception>
        private string TranslateCondition(QueryCondition condition)
        {
            return condition.Operator switch
            {
                ">" => condition.IsNumber ? $"{condition.Field} > {condition.Value}" : $"{condition.Field}  > '{condition.Value}'",
                "<" => condition.IsNumber ? $"{condition.Field} < {condition.Value}" : $"{condition.Field} < '{condition.Value}'",
                "=" => condition.IsNumber ? $"{condition.Field} = {condition.Value}" : $"{condition.Field} = '{condition.Value}'",
                _ => throw new NotSupportedException($"{nameof(TranslateCondition)} 将查询条件转换为SQL语句时操作符 {condition.Operator} 属于异常情况")
            };
        }

        /// <summary>
        /// 获取查询条件的总数量
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="options"></param>
        /// <returns></returns>
        private async Task<int> GetTotalCount<T>(IoTDBQueryOptions options) where T : IoTEntity
        {
            var countQuery = $"SELECT COUNT(*) FROM {options.TableNameOrTreePath}";
            if (options.Conditions.Any())
            {
                countQuery += " WHERE " + string.Join(" AND ", options.Conditions.Select(TranslateCondition));
            }

            var result = await CurrentSession.ExecuteQueryStatementAsync(countQuery);
            if (result == null)
            {
                return 0;
            }

            if (!result.HasNext())
            {
                return 0;
            }


            var count = Convert.ToInt32(result.Next().Values[0]);
            await result.Close();

            return count;
        }

        /// <summary>
        /// 解析查询结果
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dataSet"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        private async Task<IEnumerable<T>> ParseResults<T>(SessionDataSet dataSet, int pageSize) where T : IoTEntity, new()
        {
            var results = new List<T>();
            var metadata = await GetMetadata<T>();

            var properties = typeof(T).GetProperties();

            var columns = new List<string>() { "Timestamps" };
            var dataTypes = new List<TSDataType>() { TSDataType.TIMESTAMP };
            columns.AddRange(metadata.ColumnNames);
            dataTypes.AddRange(metadata.DataTypes);
            //metadata.ColumnNames.Insert(0, "Timestamps");
            //metadata.DataTypes.Insert(0, TSDataType.TIMESTAMP);

            while (dataSet.HasNext() && results.Count < pageSize)
            {
                var record = dataSet.Next();
                var entity = new T
                {
                    Timestamps = record.Timestamps
                };

                foreach (var measurement in columns)
                {
                    int indexOf = columns.IndexOf(measurement);
                    var value = record.Values[indexOf];
                    TSDataType tSDataType = dataTypes[indexOf];

                    var prop = properties.FirstOrDefault(p =>
                        p.Name.Equals(measurement, StringComparison.OrdinalIgnoreCase));
                    if (prop != null && !(value is System.DBNull))
                    {
                        dynamic tempValue = GetTSDataValue(tSDataType, value);

                        if (measurement.ToLower().EndsWith("time"))
                        {
                            typeof(T).GetProperty(measurement)?.SetValue(entity, TimestampHelper.ConvertToDateTime(tempValue, TimestampUnit.Nanoseconds));
                        }
                        else
                        {
                            typeof(T).GetProperty(measurement)?.SetValue(entity, tempValue);
                        }
                    }

                }

                results.Add(entity);

            }
            await dataSet.Close();
            return results;
        }

        /// <summary>
        /// 获取设备元数据的列
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private List<ColumnInfo> CollectColumnMetadata(Type type)
        {
            var columns = new List<ColumnInfo>();

            foreach (var prop in type.GetProperties())
            {

                string typeName = string.Empty;

                Type declaredType = prop.PropertyType;
                // 处理可空类型
                if (declaredType.IsGenericType && declaredType.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    Type underlyingType = Nullable.GetUnderlyingType(declaredType);
                    typeName = underlyingType.Name;
                }
                else
                {
                    typeName = declaredType.Name;
                }

                //先获取Tag标签和属性标签
                ColumnInfo? column = prop.GetCustomAttribute<TAGColumnAttribute>() is not null ? new ColumnInfo(
                        name: prop.Name,
                        category: ColumnCategory.TAG,
                        dataType: GetDataTypeFromTypeName(typeName),
                        false
                    ) : prop.GetCustomAttribute<ATTRIBUTEColumnAttribute>() is not null ? new ColumnInfo(
                        prop.Name,
                        ColumnCategory.ATTRIBUTE,
                        GetDataTypeFromTypeName(typeName),
                        false
                    ) : prop.GetCustomAttribute<FIELDColumnAttribute>() is not null ? new ColumnInfo(
                        prop.Name,
                        ColumnCategory.FIELD,
                        GetDataTypeFromTypeName(typeName),
                        false)
                      : null;

                //最先检查是不是单侧点模式
                SingleMeasuringAttribute singleMeasuringAttribute = prop.GetCustomAttribute<SingleMeasuringAttribute>();

                if (singleMeasuringAttribute != null && column == null)
                {
                    //warning: 单侧点模式注意事项
                    //Entity实体 字段类型是 Tuple<string,T>,Item1=>测点名称，Item2=>测点值,泛型
                    //只有一个Filed字段。
                    //MeasuringName 默认为 SingleMeasuringAttribute.FieldName，以便于在获取对应的Value的时候重置为 Item1 的值。

                    Type tupleType = prop.PropertyType;
                    Type[] tupleArgs = tupleType.GetGenericArguments();

                    column = new ColumnInfo(
                        singleMeasuringAttribute.FieldName,
                        ColumnCategory.FIELD,
                        GetDataTypeFromTypeName(tupleArgs[1].Name),
                        true
                    );
                }

                if (column.HasValue)
                {
                    columns.Add(column.Value);
                }
            }
            return columns;
        }

        /// <summary>
        /// 构建设备元数据
        /// </summary>
        /// <param name="typeInfo">待解析的类</param>
        /// <param name="columns">已处理好的数据列</param>
        /// <returns></returns>
        private DeviceMetadata BuildDeviceMetadata<T>(List<ColumnInfo> columns) where T : IoTEntity
        {
            var metadata = new DeviceMetadata();

            //先检查是不是单侧点模型
            if (columns.Any(c => c.IsSingleMeasuring))
            {
                metadata.IsSingleMeasuring = true;
            }

            //按业务逻辑顺序处理（TAG -> ATTRIBUTE -> FIELD）
            var groupedColumns = columns
                .GroupBy(c => c.Category)
                .ToDictionary(g => g.Key, g => g.ToList());

            ProcessCategory(groupedColumns, ColumnCategory.TAG, metadata);
            ProcessCategory(groupedColumns, ColumnCategory.ATTRIBUTE, metadata);
            ProcessCategory(groupedColumns, ColumnCategory.FIELD, metadata);

            var entityTypeAttribute = typeof(T).GetCustomAttribute<EntityTypeAttribute>();

            if (entityTypeAttribute == null)
            {
                throw new ArgumentException($"{nameof(BuildDeviceMetadata)} 构建设备元数据时 {nameof(IoTEntity)} 的EntityType 没有指定，属于异常情况，-101");
            }

            metadata.EntityType = entityTypeAttribute.EntityType;

            return metadata;
        }

        /// <summary>
        /// 处理不同列类型的逻辑
        /// </summary>
        /// <param name="groupedColumns"></param>
        /// <param name="category"></param>
        /// <param name="metadata"></param>
        private void ProcessCategory(IReadOnlyDictionary<ColumnCategory, List<ColumnInfo>> groupedColumns, ColumnCategory category, DeviceMetadata metadata)
        {
            if (groupedColumns.TryGetValue(category, out var cols))
            {
                metadata.ColumnNames.AddRange(cols.Select(c => c.Name));
                metadata.ColumnCategories.AddRange(cols.Select(c => c.Category));
                metadata.DataTypes.AddRange(cols.Select(c => c.DataType));
            }
        }

        /// <summary>
        /// 数据列结构
        /// </summary>
        private readonly struct ColumnInfo
        {
            /// <summary>
            /// 列名
            /// </summary>
            public string Name { get; }

            /// <summary>
            /// 是否是单测点
            /// </summary>
            public bool IsSingleMeasuring { get; }

            /// <summary>
            /// 列类型
            /// </summary>
            public ColumnCategory Category { get; }

            /// <summary>
            /// 数据类型
            /// </summary>
            public TSDataType DataType { get; }

            public ColumnInfo(string name, ColumnCategory category, TSDataType dataType, bool isSingleMeasuring)
            {
                Name = name;
                Category = category;
                DataType = dataType;
                IsSingleMeasuring = isSingleMeasuring;
            }
        }

        /// <summary>
        /// 根据类型名称获取对应的 IoTDB 数据类型
        /// </summary>
        /// <param name="typeName">类型名称（不区分大小写）</param>
        /// <returns>对应的 TSDataType，默认返回 TSDataType.STRING</returns>
        private TSDataType GetDataTypeFromTypeName(string typeName)
        {
            if (string.IsNullOrWhiteSpace(typeName))
                return TSDataType.STRING;

            return DataTypeMap.TryGetValue(typeName.Trim(), out var dataType)
                ? dataType
                : TSDataType.STRING;
        }

        /// <summary>
        /// 根据类型名称获取 IoTDB 数据类型
        /// </summary>
        private readonly IReadOnlyDictionary<string, TSDataType> DataTypeMap =
            new Dictionary<string, TSDataType>(StringComparer.OrdinalIgnoreCase)
            {
                ["BOOLEAN"] = TSDataType.BOOLEAN,
                ["INT32"] = TSDataType.INT32,
                ["INT64"] = TSDataType.INT64,
                ["FLOAT"] = TSDataType.FLOAT,
                ["DOUBLE"] = TSDataType.DOUBLE,
                ["TEXT"] = TSDataType.TEXT,
                ["NULLTYPE"] = TSDataType.NONE,
                ["DATETIME"] = TSDataType.TIMESTAMP,
                ["DATE"] = TSDataType.DATE,
                ["BLOB"] = TSDataType.BLOB,
                ["DECIMAL"] = TSDataType.STRING,
                ["STRING"] = TSDataType.STRING
            };

        /// <summary>
        /// 根据类型名称获取 IoTDB 数据默认值
        /// </summary>
        private readonly IReadOnlyDictionary<string, object> DataTypeDefaultValueMap =
            new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
            {
                ["BOOLEAN"] = false,
                ["INT32"] = 0,
                ["INT64"] = 0,
                ["FLOAT"] = 0.0f,
                ["DOUBLE"] = 0.0d,
                ["TEXT"] = string.Empty,
                ["NULLTYPE"] = null,
                ["DATETIME"] = null,
                ["DATE"] = null,
                ["BLOB"] = null,
                ["DECIMAL"] = "0.0",
                ["STRING"] = string.Empty
            };

        /// <summary>
        /// IoTDB 数据类型与.net类型映射
        /// </summary>
        /// <param name="tSDataType"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private dynamic GetTSDataValue(TSDataType tSDataType, object value) =>
         tSDataType switch
         {
             TSDataType.BOOLEAN => Convert.ToBoolean(value),
             TSDataType.INT32 => Convert.ToInt32(value),
             TSDataType.INT64 => Convert.ToInt64(value),
             TSDataType.FLOAT => Convert.ToDouble(value),
             TSDataType.DOUBLE => Convert.ToDouble(value),
             TSDataType.TEXT => Convert.ToString(value),
             TSDataType.NONE => null,
             TSDataType.TIMESTAMP => Convert.ToInt64(value),
             TSDataType.DATE => Convert.ToDateTime(value),
             TSDataType.BLOB => Convert.ToByte(value),
             TSDataType.STRING => Convert.ToString(value),
             _ => Convert.ToString(value)
         };
    }
}
