using System.ComponentModel.DataAnnotations.Schema;

using App.Module.Sqler.Logical.DataEditor;
using App.Module.Sqler.Logical.DataEditor.GridManage;

using Vit.AutoTemp;
using Vit.Core.Module.Serialization;
using Vit.Db.Module.Schema;
using Vit.Extensions.Serialize_Extensions;
using Vit.Linq.ExpressionNodes.ComponentModel;

using Vitorm.EntityGenerate;

using static Vit.AutoTemp.AutoTempControllerConfig;

namespace Sqler.DataEditor.Config
{
    [Table("Sqler_DataEditor_TableSchema")]
    public class TableSchemaEntity
    {
        /// <summary>
        /// {schema_name}.{table_name}
        /// </summary>
        [System.ComponentModel.DataAnnotations.Key]
        public string templateName { get; set; }


        /// <summary>
        /// {schema_name}.{table_name}
        /// </summary>
        public string tableName { get; set; }

        [Column(TypeName = "text")]
        public string columns { get; set; }

        [Column(TypeName = "text")]
        public string autoTemp_Config { get; set; }

        public int? sortIndex { get; set; }



        #region Column
        public List<Column> GetColumns()
        {
            return Json.Deserialize<List<Column>>(columns) ?? new();
        }

        public void SetColumns(List<Column> cols)
        {
            columns = Json.Serialize(cols);
        }

        public class Column : ColumnSchema
        {
            public int sortIndex;
            public string autoTemp_Config;
            public new string column_clr_type
            {
                get => Json.Serialize(NodeValueType.FromType(base.column_clr_type));
                set => base.column_clr_type = Json.Deserialize<NodeValueType>(value)?.ToType();
            }

            public Column SetClrType(Type clr_type)
            {
                base.column_clr_type = clr_type;
                return this;
            }

            public AutoTempModel_Grid ToAutoTemplateModel(string templateName)
            {
                var col = this.ConvertBySerialize<AutoTempModel_Grid>();

                col.pid = templateName;
                col.id = templateName + "." + column_name;
                col.name = column_name;
                col.templateName = templateName;
                col.autoTemp_Config = autoTemp_Config;

                return col;
            }

            public static Column FromAutoTemplateModel(AutoTempModel_Grid model)
            {
                var col = model.ConvertBySerialize<Column>();

                col.column_name = model.name;

                return col;
            }
        }
        #endregion


        public static TableSchemaEntity FromTableSchema(TableSchema tableSchema)
        {
            var entity = new TableSchemaEntity();

            entity.tableSchema_ = tableSchema;

            if (string.IsNullOrWhiteSpace(tableSchema.schema_name))
                entity.tableName = tableSchema.table_name;
            else entity.tableName = tableSchema.schema_name + "." + tableSchema.table_name;


            AutoTempControllerConfig defaultConfig = AutoTempHelp.BuildControllerConfigByTable(tableSchema);
            var defaultFields = defaultConfig.fields;
            defaultConfig.fields = null;

            entity.autoTemp_Config = Json.Serialize(defaultConfig);

            var columns = tableSchema.columns?.Select((col, index) =>
            {
                return new Column
                {
                    sortIndex = index,
                    column_name = col.column_name,
                    primary_key = col.primary_key,
                    autoincrement = col.autoincrement,
                    column_comment = col.column_comment,
                    column_type = col.column_type,
                    autoTemp_Config = Json.Serialize(defaultFields.FirstOrDefault(m => m.field == col.column_name)),
                }.SetClrType(col.column_clr_type);
            }).ToList();

            entity.SetColumns(columns);
            return entity;
        }



        [NotMapped]
        public TableSchema tableSchema => tableSchema_ ??= new TableSchema() { table_name = tableName, columns = GetColumns().Select(col => (ColumnSchema)col).ToList() };
        private TableSchema tableSchema_;



        [NotMapped]
        public Type entityType => entityType_ ??= EntityHelp.GenerateEntityBySchema(tableSchema, DataEditorHelp.entityNamespace);

        private Type entityType_;



        [NotMapped]
        public AutoTempControllerConfig controllerConfig
        {
            get
            {
                if (controllerConfig_ != null) return controllerConfig_;

                AutoTempControllerConfig defaultConfig = AutoTempHelp.BuildControllerConfigByTable(tableSchema);
                var defaultFields = defaultConfig.fields;

                if (string.IsNullOrWhiteSpace(autoTemp_Config))
                {
                    controllerConfig_ = defaultConfig;
                }
                else
                {
                    controllerConfig_ = Json.Deserialize<AutoTempControllerConfig>(autoTemp_Config);
                }

                controllerConfig_.fields = GetColumns()
                    .OrderBy(col => col.sortIndex)
                    .Select(col => string.IsNullOrWhiteSpace(col.autoTemp_Config) ? defaultFields.FirstOrDefault(m => m.field == col.column_name) : Json.Deserialize<FieldConfig>(col.autoTemp_Config))
                    .ToList();

                return controllerConfig_;
            }
        }
        private AutoTempControllerConfig controllerConfig_;



    }


}
