using Infrastructure;
using Infrastructure.Extensions;
using Infrastructure.Utilities;
using Microsoft.Extensions.Configuration;
using NUnit.Framework;
using OpenAuth.App.Base;
using OpenAuth.App.FormScheme.FormHelpers;
using OpenAuth.Repository;
using OpenAuth.Repository.Domain;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenAuth.App.BaseApp.Base;
using static Microsoft.Extensions.Logging.EventSource.LoggingEventSource;

namespace OpenAuth.App.CodeTable
{
    public class CodeTableApp : SqlSugarBaseApp<Repository.Domain.DbCodeTable, SugarDbContext>
    {
        CodeColumnsApp _codeColumnsApp;
        private IConfiguration _configuration;
        public CodeTableApp(ISugarUnitOfWork<SugarDbContext> unitWork, ISimpleClient<Repository.Domain.DbCodeTable> repository, CodeColumnsApp codeColumnsApp, IConfiguration configuration) : base(unitWork, repository, null)
        {
            _codeColumnsApp = codeColumnsApp;
            _configuration = configuration;
        }

        /// <summary>
        /// 获取CodeTable的分页数据
        /// </summary>
        /// <param name="keyword">查询关键字</param>
        /// <param name="dbCode">数据库编码</param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public async Task<Response<PageInfo<List<DbCodeTable>>>> LoadCodeTablePage(string keyWord, string dbCode, int page, int limit)
        {
            RefAsync<int> totalCount = 0;
            var info = await base.Repository.AsQueryable()
                .WhereIF(!string.IsNullOrEmpty(keyWord), t => t.ClassName.Contains(keyWord) || t.TableName.Contains(keyWord) || t.Description.Contains(keyWord))
                .WhereIF(!string.IsNullOrEmpty(dbCode), t => t.DbId == dbCode)
                .ToPageListAsync(page, limit, totalCount);
            return new Response<PageInfo<List<DbCodeTable>>>
            {
                Result = new PageInfo<List<DbCodeTable>>
                {
                    Items = info,
                    Total = totalCount
                }
            };
        }
        /// <summary>
        /// 获取实体集合
        /// </summary>
        /// <param name="dbCode">数据库编码</param>
        /// <param name="tableNames">数据库表名</param>
        /// <returns></returns> 
        public async Task<List<DbCodeTable>> GetEntitys(string dbCode, List<string> tableNames)
        {
            var list = await base.Repository.AsQueryable()
                    .Where(t => t.DbId == dbCode && tableNames.Contains(t.TableName))
                    .ToListAsync();
            return list;
        }
        /// <summary>
        /// 获取列表数据
        /// </summary>
        /// <param name="dbCode">数据库编码</param>
        /// <returns></returns>
        public Task<List<DbCodeTable>> GetList(string dbCode)
        {

            return base.Repository.AsQueryable().Where(t => t.DbId == dbCode).ToListAsync();
        }
        /// <summary>
        /// 跨服务器获取表单字段
        /// </summary>
        /// <param name="code"></param>
        /// <param name="isCache"></param>
        /// <returns></returns>
        public List<DbColumnInfo> GetTableColumnList(string code, string tableName)
        {
            using (var db = this.CodeClient(code, _configuration))
            {
                //var list= this.Repository.AsSugarClient().DbMaintenance.GetTableInfoList(isCache);
                var list = db.DbMaintenance.GetColumnInfosByTableName(tableName,false);
                return list;
            }

        }
        /// <summary>
        /// 导入表信息
        /// </summary>
        /// <param name="dbcode">数据库编码</param>
        /// <param name="tableList">数据表信息</param>
        /// <returns></returns>
        public async Task ImportTable(string dbcode, List<DbTableInfo> tableList)
        {
            using (SugarDbContext db = base.UnitWork.CreateContext())
            {
                var oldTables = await GetList(dbcode);
                List<DbCodeColumns> updateList = new List<DbCodeColumns>();
                List<DbCodeColumns> addList = new List<DbCodeColumns>();
                List<DbCodeColumns> deleteList = new List<DbCodeColumns>();
                foreach (var tableItem in tableList)
                {
                    //排除中间表
                    if (tableItem.Name.ToLower() == "db_codecolumns" || tableItem.Name.ToLower() == "db_codetable" || tableItem.Name.ToLower() == "db_history")
                    {
                        continue;
                    }
                    DbCodeTable entity = oldTables.FirstOrDefault(t => t.TableName == tableItem.Name);
                    //var dbColumns = db.Db.DbMaintenance.GetColumnInfosByTableName(tableItem.Name, false);
                    var dbColumns = GetTableColumnList(dbcode, tableItem.Name);
                    foreach (var item in dbColumns)
                    {
                        item.PropertyName = FormHelper.GetCsType(SqlSugar.DbType.Kdbndp, item.DataType);
                    }
                    int columnSort = 1;
                    if (entity == null)
                    {
                        // 新增
                        entity = new DbCodeTable();
                        entity.DbId = dbcode;
                        entity.ClassName = StringExtension.CsharpName(tableItem.Name);
                        entity.TableName = tableItem.Name;
                        entity.Description = tableItem.Description;
                        entity.IsLock = 0;
                        entity.DeleteMark = 0;
                        entity.State = 1;
                        await SaveEntity(null, entity);

                        // 新增列
                        foreach (var dbColumnItem in dbColumns)
                        {
                            var codeColumnsEntity = CreateColumn(dbColumnItem);
                            codeColumnsEntity.CodeTableId = entity.Id;
                            codeColumnsEntity.Id = Guid.NewGuid().ToString();
                            codeColumnsEntity.Sort = columnSort;
                            columnSort++;
                            addList.Add(codeColumnsEntity);
                        }
                    }
                    else
                    {
                        // 编辑
                        if (entity.Description != tableItem.Description
                            || entity.State != 1
                            || entity.IsLock != 0
                            || entity.DeleteMark != 0
                            )
                        {
                            entity.State = 1;
                            entity.Description = tableItem.Description;
                            entity.IsLock = 0;
                            entity.DeleteMark = 0;
                            await SaveEntity(entity.Id, entity);
                        }
                        var oldColumns = await _codeColumnsApp.GetList(new DbCodeColumns { CodeTableId = entity.Id });
                        foreach (var dbColumnItem in dbColumns)
                        {
                            var codeColumnsEntity = CreateColumn(dbColumnItem);
                            codeColumnsEntity.CodeTableId = entity.Id;
                            codeColumnsEntity.Sort = columnSort;
                            columnSort++;

                            var oldColumn = oldColumns.Find(t => t.DbColumnName == dbColumnItem.DbColumnName);
                            if (oldColumn == null)
                            {
                                codeColumnsEntity.Id = Guid.NewGuid().ToString();
                                addList.Add(codeColumnsEntity);
                            }
                            else
                            {
                                codeColumnsEntity.Id = oldColumn.Id;
                                updateList.Add(codeColumnsEntity);
                            } 
                        }
                        // 获取需要删除的列
                        var deleteColumns = oldColumns.FindAll(t => updateList.FindIndex(t2 => t2.Id == t.Id) == -1);
                        deleteList.AddRange(deleteColumns);
                    }
                }
                //await _codeColumnsApp.Add(addList); 
                //await _codeColumnsApp.Update(updateList);
                //await _codeColumnsApp.Deletes(deleteList);
                await db.DbCodeColumns.InsertRangeAsync(addList);
                await db.DbCodeColumns.UpdateRangeAsync(updateList);
                await db.DbCodeColumns.DeleteAsync(deleteList);
                db.Commit();
            }
        }
        #region 操作方法
        /// <summary>
        /// 保存(新增,更新)
        /// </summary>
        /// <param name="Id">唯一标识码(GUID)</param>
        /// <param name="dbCodeTable">数据库表信息db_codetable实体数据</param>
        public async Task SaveEntity(string Id, DbCodeTable dbCodeTable)
        {
            if (!string.IsNullOrEmpty(Id)) // 更新
            {
                dbCodeTable.Id = Id;
                await base.Repository.UpdateAsync(dbCodeTable);
            }
            else // 新增
            {
                if (string.IsNullOrEmpty(dbCodeTable.Id))
                {
                    dbCodeTable.Id = Guid.NewGuid().ToString();
                }
                await base.Repository.InsertAsync(dbCodeTable);
            }
        }
        /// <summary>
        /// 获取类字段信息
        /// </summary>
        /// <param name="dbColumnInfo">数据库字段信息</param>
        /// <returns></returns>
        private DbCodeColumns CreateColumn(DbColumnInfo dbColumnInfo)
        {
            var codeColumns = new DbCodeColumns();
            codeColumns.DbColumnName = dbColumnInfo.DbColumnName;
            codeColumns.IsNullable = dbColumnInfo.IsNullable == true ? 1 : 0;
            codeColumns.IsIdentity = dbColumnInfo.IsIdentity == true ? 1 : 0;
            codeColumns.IsPrimaryKey = dbColumnInfo.IsPrimarykey == true ? 1 : 0;
            codeColumns.Description = dbColumnInfo.ColumnDescription;
            codeColumns.CsType = dbColumnInfo.PropertyName;
            codeColumns.DbType = dbColumnInfo.DataType;
            codeColumns.Length = dbColumnInfo.Length;
            codeColumns.DecimalDigits = dbColumnInfo.DecimalDigits;
            return codeColumns;
        }
        #endregion
        #region 获取表及视图字段
        /// <summary>
        /// 获取表及视图字段
        /// </summary>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public List<dynamic> GetTableAndViewColumnList(string dbCode, string tableName)
        {
            using (var db = this.CodeClient(dbCode, _configuration))
            {
                string query = $@"
                             SELECT 
                                 c.column_name, 
                                 d.description
                             FROM 
                                 information_schema.columns c
                             LEFT JOIN 
                                 pg_catalog.pg_class t ON t.relname = c.table_name
                             LEFT JOIN 
                                 pg_catalog.pg_attribute a ON a.attnum > 0 
                                 AND a.attrelid = t.oid 
                                 AND a.attname = c.column_name
                             LEFT JOIN 
                                 pg_catalog.pg_namespace n ON n.oid = t.relnamespace
                             LEFT JOIN 
                                 pg_catalog.pg_description d ON d.objoid = a.attrelid 
                                 AND d.objsubid = a.attnum
                             WHERE 
                                 c.table_name = @tableName 
                                 AND c.table_schema = 'public';";
                // 执行查询并获取结果
                var viewColumns = db.Ado.SqlQuery<dynamic>(query, new { tableName = tableName });
                return viewColumns;
            }

        }
        #endregion
    }
}
