using Infrastructure;
using OpenAuth.App.Base;
using OpenAuth.App.FormScheme;
using OpenAuth.App.Permission;
using OpenAuth.Repository;
using OpenAuth.Repository.Domain;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenAuth.App.BaseApp.Base;

namespace OpenAuth.App.Import
{
    public class ImportApp : SqlSugarBaseApp<Repository.Domain.ExcelImport, SugarDbContext>
    {
        SysDataItemDetailApp _dataItemDetailApp;
        FormSchemeApp _formSchemeApp;
        public ImportApp(ISugarUnitOfWork<SugarDbContext> unitWork, SysDataItemDetailApp dataItemDetailApp, FormSchemeApp formSchemeApp,
        ISimpleClient<Repository.Domain.ExcelImport> repository)
            : base(unitWork, repository, null)
        {
            _dataItemDetailApp = dataItemDetailApp;
            _formSchemeApp = formSchemeApp;
        }

        /// <summary>
        /// 获取导入的分页数据
        /// </summary>
        /// <param name="keyWord">查询关键字</param>
        /// <param name="moduleId">菜单id</param>
        /// <param name="page"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        public async Task<Response<PageInfo<List<ExcelImport>>>> LoadExcelImportPage(string keyWord, string moduleId, int page, int limit)
        {
            RefAsync<int> totalCount = 0;
            var expression = Expressionable.Create<ExcelImport>()
               .AndIF(!string.IsNullOrEmpty(keyWord), t => t.Name.Contains(keyWord))
               .AndIF(!string.IsNullOrEmpty(moduleId), t => t.ModuleId == moduleId);
            var info = await base.Repository.AsQueryable()
                 .Where(expression.ToExpression())
                .ToPageListAsync(page, limit, totalCount);
            return new Response<PageInfo<List<ExcelImport>>>
            {
                Result = new PageInfo<List<ExcelImport>>
                {
                    Items = info,
                    Total = totalCount
                }
            };
        }

        /// <summary>
        /// 获取表单数据
        /// </summary>
        /// <param name="id">id</param> 
        /// <returns></returns> 
        public async Task<ExcelImport> GetEntity(string id)
        {
            var entity = await base.Repository.AsQueryable()
                    .Where(t => t.Id == id)
                    .FirstAsync();
            return entity;
        }
        /// <summary>
        /// 获取配置字段列表
        /// </summary>
        /// <param name="importId">配置信息主键</param>
        /// <returns></returns>
        public Task<List<ExcelImportFileds>> GetFieldList(string importId)
        {
            return base.Repository.ChangeRepository<SugarRepositiry<Repository.Domain.ExcelImportFileds>>().AsQueryable().Where(t => t.ImportId == importId).ToListAsync();
        }
        /// <summary>
        /// 获取导入配置列表根据模块ID
        /// </summary>
        /// <param name="moduleId">功能模块主键</param>
        /// <returns></returns>
        public async Task<List<ExcelImport>> GetModuleList(string moduleId)
        {
            var expression = Expressionable.Create<ExcelImport>();
            expression = expression.And(t => t.ModuleId == moduleId && t.EnabledMark == 1);
            return await base.Repository.AsQueryable().Where(expression.ToExpression()).ToListAsync();
        }
        /// <summary>
        /// 删除数据
        /// </summary>
        /// <param name="keyValue">主键</param>
        public async Task<Response<bool>> DeleteEntity(string keyValue)
        {
            using (var uow = base.UnitWork.CreateContext())
            {
                await uow.ExcelImport.DeleteByIdAsync(keyValue);
                await uow.ExcelImportFileds.DeleteAsync(a => a.ImportId == keyValue);

                var falg = uow.Commit();
                return new Response<bool>
                {
                    Result = falg,
                    Message = (falg == true ? "success" : "error")
                };
            }
        }

        /// <summary>
        /// 保存表单（新增、修改）
        /// </summary>
        /// <param name="keyValue">主键值</param>
        /// <param name="entity">实体数据</param>
        /// <param name="filedList">字段列表</param>
        /// <returns></returns>
        public async Task<Response<bool>> SaveEntity(string keyValue, ExcelImport entity, List<ExcelImportFileds> filedList)
        {
            using (var uow = base.UnitWork.CreateContext())
            {
                if (!string.IsNullOrEmpty(keyValue))
                {
                    entity.Id = keyValue;
                    entity.ModifyDate = DateTime.Now;
                    await uow.ExcelImport.UpdateAsync(entity);
                }
                else
                {
                    entity.Id = Guid.NewGuid().ToString();
                    entity.CreateDate = DateTime.Now;
                    entity.EnabledMark = 1;
                    await uow.ExcelImport.InsertAsync(entity);
                }
                await uow.ExcelImportFileds.DeleteAsync(t => t.ImportId == entity.Id);
                foreach (var item in filedList)
                {
                    item.ImportId = entity.Id;
                    await uow.ExcelImportFileds.InsertAsync(item);
                }
                var falg = uow.Commit();
                return new Response<bool>
                {
                    Result = falg,
                    Message = (falg == true ? "success" : "error")
                };
            }
        }

        #region 扩展方法
        /// <summary>
        /// excel 数据导入（未导入数据写入缓存）
        /// </summary>
        /// <param name="templateId">导入模板主键</param>
        /// <param name="dt">导入数据</param>
        /// <returns></returns>
        public async Task<(DataTable elist, int snum, int fnum)> ImportTable(string templateId, DataTable dt)
        {
            int snum = 0;
            int fnum = 0;
            // 创建一个datatable容器用于保存导入失败的数据
            DataTable failDt = new DataTable();
            dt.Columns.Add("导入错误", typeof(string));
            foreach (DataColumn dc in dt.Columns)
            {
                failDt.Columns.Add(dc.ColumnName, dc.DataType);
            }

            if (dt.Rows.Count > 0)
            {
                ExcelImport entity = await GetEntity(templateId);
                List<ExcelImportFileds> list = (List<ExcelImportFileds>)await GetFieldList(templateId);

                if (entity != null && list.Count > 0)
                {
                    string sqlonly = " select * from " + entity.DbTable + " where 1=1 {LEARUN_SASSID} ";
                    // 数据字典数据
                    Dictionary<string, List<SysDataItemDetail>> dataItemMap = new Dictionary<string, List<SysDataItemDetail>>();
                    Dictionary<string, DataTable> dataSourceMap = new Dictionary<string, DataTable>();

                    foreach (DataRow dr in dt.Rows)
                    { // 行数据循环
                        try
                        {
                            List<SugarParameter> dbParameters = new List<SugarParameter>();
                            foreach (var col in list)
                            {
                                object paramValue = null;

                                switch (col.RelationType)
                                {
                                    case 0://无关联
                                        paramValue = dr[col.ColName].ToString();
                                        await IsOnlyOne(col, sqlonly, dr[col.ColName].ToString(), entity.DbId);
                                        break;
                                    case 1://GUID
                                        paramValue = Guid.NewGuid().ToString();
                                        break;
                                    case 2://数据字典
                                        string dataItemName = "";
                                        if (!dataItemMap.ContainsKey(col.DataItemCode))
                                        {
                                            List<SysDataItemDetail> dataItemList = (List<SysDataItemDetail>)await _dataItemDetailApp.Load(col.DataItemCode, "");
                                            dataItemMap.Add(col.DataItemCode, dataItemList);
                                        }
                                        dataItemName = FindDataItemValue(dataItemMap[col.DataItemCode], dr[col.ColName].ToString(), col.ColName);
                                        paramValue = dataItemName;
                                        await IsOnlyOne(col, sqlonly, dataItemName, entity.DbId);
                                        break;
                                    case 3://数据表
                                        string v = "";
                                        try
                                        {
                                            //string queryJson = "{" + col.F_DSourceExcelId + ":\"" + dr[col.F_ColName].ToString() + "\"}";
                                            if (!dataSourceMap.ContainsKey(col.DSourceId))
                                            {
                                                //DataTable sourceDt = await _dataSourceIBLL.GetDataTable(col.DSourceId);
                                                DataTable sourceDt = new DataTable();
                                                dataSourceMap.Add(col.DSourceId, sourceDt);
                                            }
                                            v = FindDataSourceValue(dataSourceMap[col.DSourceId], col.DSourceExcelId.ToLower(), dr[col.ColName].ToString(), col.DSourceDBId.ToLower());
                                            paramValue = v;
                                        }
                                        catch (Exception)
                                        {
                                            throw (new Exception("【" + col.ColName + "】 找不到对应的数据"));
                                        }
                                        await IsOnlyOne(col, sqlonly, v, entity.DbId);
                                        break;
                                    case 4://固定值
                                        paramValue = col.Value;
                                        break;
                                    case 5://操作人ID
                                        paramValue = "";
                                        break;
                                    case 6://操作人名字
                                        paramValue = "";
                                        break;
                                    case 7://操作时间
                                        paramValue = DateTime.Now;
                                        break;
                                }

                                dbParameters.Add(new SugarParameter(col.Name, paramValue));
                            }

                            //await excelImportService.BaseRepository(entity.DbId).ExecuteInsert(entity.DbTable, dbParameters); 
                            _formSchemeApp.ExecuteInsert(entity.DbTable, dbParameters);
                            snum++;
                        }
                        catch (Exception ex)
                        {
                            fnum++;
                            if (entity.ErrorType == 0)// 如果错误机制是终止
                            {
                                dr["导入错误"] = $"{ex.Message} 【之后数据未被导入】";
                                failDt.Rows.Add(dr.ItemArray);
                                break;
                            }
                            else
                            {
                                dr["导入错误"] = ex.Message;
                                failDt.Rows.Add(dr.ItemArray);
                            }
                        }
                    }
                }
            }
            return (failDt, snum, fnum);
        }

        /// <summary>
        /// 数据字典查找Value
        /// </summary>
        /// <param name="dataItemList">数据字典数据</param>
        /// <param name="itemName">项目名</param>
        /// <param name="colName">列名</param>
        /// <returns></returns>
        private string FindDataItemValue(List<SysDataItemDetail> dataItemList, string itemName, string colName)
        {
            SysDataItemDetail dataItem = dataItemList.Find(t => t.ItemName == itemName);
            if (dataItem != null)
            {
                return dataItem.ItemValue;
            }
            else
            {
                throw (new Exception("【" + colName + "】数据字典找不到对应值"));
            }
        }


        /// <summary>
        /// 获取数据源数据
        /// </summary>
        /// <param name="dt">数据源</param>
        /// <param name="name">名称</param>
        /// <param name="value">值</param>
        /// <param name="colname">列名</param>
        /// <returns></returns>
        private string FindDataSourceValue(DataTable dt, string name, string value, string colname)
        {

            foreach (DataRow dr in dt.Rows)
            {
                if (dr[name].ToString() == value)
                {
                    return dr[colname].ToString();
                }
            }

            return "";
        }

        /// <summary>
        /// 判断是否数据有重复
        /// </summary>
        /// <param name="col"></param>
        /// <param name="sqlonly"></param>
        /// <param name="value"></param>
        /// <param name="dbId"></param>
        private async Task IsOnlyOne(ExcelImportFileds col, string sqlonly, string value, string dbId)
        {
            if (col.OnlyOne == 1)
            {
                var dp = new Dictionary<string, string>();
                sqlonly += col.Name + " = @" + col.Name;
                dp.Add(col.Name, value);
                var d = await _formSchemeApp.FindTableNew(sqlonly, dp);
                if (d.Count > 0)
                {
                    throw new Exception("【" + col.ColName + "】此项数据不能重复");
                }
            }
        }

        #endregion
    }
}
