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

using Sqler.DataEditor.Config;

using Vit.AutoTemp;
using Vit.AutoTemp.DataProvider;
using Vit.Extensions.Db_Extensions;

using Vitorm;
using Vitorm.Sql;

using static Sqler.DataEditor.Config.TableSchemaEntity;

namespace Sqler.Module.Sqler.Logical.DataEditor.GridManage
{
    public class GridService
    {

        public static IDataProvider[] dataProviders = null;
        public static IQueryable<AutoTempModel_Grid> models => Data.Query<TableSchemaEntity>().ToList().SelectMany(ToAutoTemplateModel).AsQueryable();


        #region BuildDataProvidersFromConfig

        static SqlDbContext CreateSqlDbContext() => Data.DataProvider(DataEditorHelp.entityNamespace).CreateSqlDbContext();
        public static IDataProvider[] BuildDataProvidersFromConfig()
        {
            var entities = Data.Query<TableSchemaEntity>().ToList();

            if (!entities.Any())
            {
                using var dbContext = CreateSqlDbContext();
                var dbConn = dbContext.dbConnection;
                var tableSchemaList = dbConn.GetSchema().Where(schema => schema.table_name?.StartsWith("Sqler_") == false).ToList();
                entities = tableSchemaList.Select(m => TableSchemaEntity.FromTableSchema(m)).ToList();

                entities.ForEach(entity => entity.templateName = "Sqler_DataEditor_Db_" + entity.tableName);

                Data.AddRange(entities);
            }

            dataProviders = entities.Select((entity) =>
            {
                var dataProvider = AutoTempHelp.CreateDataProvider(entity.templateName, entity.entityType, CreateSqlDbContext, entity.tableSchema, entity.controllerConfig);
                return (IDataProvider)dataProvider;
            }
            ).ToArray();

            return dataProviders;
        }

        #endregion


        public static IEnumerable<AutoTempModel_Grid> ToAutoTemplateModel(TableSchemaEntity entity)
        {
            // table
            var modelTable = new AutoTempModel_Grid();
            modelTable.templateName = entity.templateName;
            modelTable.name = entity.tableName;
            modelTable.pid = "0";
            modelTable.id = entity.templateName;
            modelTable.autoTemp_Config = entity.autoTemp_Config;
            modelTable.sortIndex = entity.sortIndex;
            yield return modelTable;

            // columns
            var columns = entity.GetColumns();
            if (columns?.Any() != true) yield break;

            foreach (var column in columns)
            {
                yield return column.ToAutoTemplateModel(entity.templateName);
            }
        }


        public static AutoTempModel_Grid Upsert(AutoTempModel_Grid model, string id)
        {
            var oldTemplateName = id?.Split('.')[0];
            var entity = Data.Get<TableSchemaEntity>(oldTemplateName);

            if (model.pid == "0")
            {
                // table
                if (entity == null)
                {
                    entity = new() { templateName = model.templateName, tableName = model.name, sortIndex = model.sortIndex };
                    Data.Add(entity);

                    return model;
                }
                else
                {
                    Data.Delete(entity);

                    entity.tableName = model.name;
                    entity.templateName = model.templateName;
                    entity.autoTemp_Config = model.autoTemp_Config;
                    entity.sortIndex = model.sortIndex;

                    Data.Add(entity);

                    return model;
                }
            }
            else
            {
                // column
                if (entity == null)
                {
                    throw new Exception("can not insert column to a not existed template");
                }

                var columns = entity.GetColumns();

                columns.RemoveAll(col => col.column_name == model.name);

                columns.Add(Column.FromAutoTemplateModel(model));

                columns = columns.OrderBy(col => col.sortIndex).ToList();

                entity.SetColumns(columns);

                Data.Update(entity);
                return model;
            }
        }

        public static bool Delete(AutoTempModel_Grid model)
        {
            var entity = Data.Get<TableSchemaEntity>(model.templateName);
            if (entity == null) return false;

            if (model.pid == "0")
            {
                // table
                Data.Delete(entity);
                return true;
            }
            else
            {
                // column
                var columns = entity.GetColumns();

                var column = columns.FirstOrDefault(col => col.column_name == model.name);

                if (column == null) return false;
                columns.Remove(column);
                entity.SetColumns(columns);

                Data.Update(entity);
                return true;

            }

        }
    }
}
