using System.Collections.Generic;
using System.Threading.Tasks;
using AutoMapper;
using Dapper;
using GxPress.Common.AppOptions;
using GxPress.Common.Exceptions;
using GxPress.Common.Tools;
using GxPress.Entity.Middle;
using GxPress.Repository.Interface;
using GxPress.Request.Notice;
using Microsoft.Extensions.Options;
using SqlKata;
using Datory;
using GxPress.Request.App.Middle;
using System;
using GxPress.Request.Inbox;

namespace GxPress.Repository.Implement
{
    public class MiddleRepository : IMiddleRepository
    {
        private readonly Repository<Middle> _repository;
        private readonly IMapper _mapper;
        private readonly string _connectionString;
        private readonly string _databaseTypeStr;
        public MiddleRepository(IOptionsMonitor<DatabaseOptions> dbOptionsAccessor, IMapper mapper)
        {
            _databaseTypeStr = dbOptionsAccessor.CurrentValue.DatabaseType;
            _connectionString = dbOptionsAccessor.CurrentValue.ConnectionString;
            var databaseType =
                StringUtils.ToEnum<DatabaseType>(dbOptionsAccessor.CurrentValue.DatabaseType, DatabaseType.MySql);
            var database = new Database(databaseType, dbOptionsAccessor.CurrentValue.ConnectionString);
            _repository = new Repository<Middle>(database);
            _mapper = mapper;
        }

        public IDatabase Database => _repository.Database;
        public string TableName => _repository.TableName;
        public List<TableColumn> TableColumns => _repository.TableColumns;
        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="middle"></param>
        /// <returns></returns>
        public async Task<int> InsertAsync(Middle middle)
        {
            middle.IsTop = false;
            middle.IsDelete = false;
            middle.IsRead = false;
            return await _repository.InsertAsync(middle);
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="middle"></param>
        /// <returns></returns>
        public async Task<bool> InsertAsync(List<Middle> middles)
        {
            if (middles.Count == 0)
                return false;
            var sql = "INSERT INTO `tede_middle`(`Guid`,`CreatedDate`,`LastModifiedDate`,`FolderName`,`FolderType`,`IsTop`,`RoleId`,`Sort`,`MiddleId`,`ParentId`,`UserId`,`MiddleSonId`,`IsRead`,`NoticeAddresseeType`,`IsAdmin`,`IsDelete`,`AttributeValue`,`IsDefault`,`IsUpload`,`Title`,`TitleLong`,`Content`,`AddressUser`,`CcUser`,`AddressUserComplete`,`CcUserComplete`,`IsRecall`)VALUES";
            foreach (var item in middles)
            {
                var guId = Guid.NewGuid().ToString();
                var createdDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                var isRead = item.IsRead == true ? 1 : 0;
                var isDefault = item.IsDefault == true ? 1 : 0;
                var isDelete = item.IsDelete == true ? 1 : 0;
                var isAdmin = item.IsAdmin == true ? 1 : 0;
                var isRecall = item.IsRecall == true ? 1 : 0;
                sql += $"('{guId}','{createdDate}','{createdDate}','{item.FolderName}',{item.FolderType},{item.IsTop},{item.RoleId},{item.Sort},{item.MiddleId},{item.ParentId},{item.UserId},{item.MiddleSonId},{isRead},{item.NoticeAddresseeType.GetHashCode()},{isAdmin},{isDelete},{item.AttributeValue},{isDefault},0,'{item.Title}','{item.TitleLong}','{item.Content}','{item.AddressUser}','{item.CcUser}','{item.AddressUserComplete}','{item.CcUserComplete}',{isRecall}),";
            }
            sql = sql.Remove(sql.Length - 1, 1);
            var databaseType = StringUtils.ToEnum<DatabaseType>(_databaseTypeStr, DatabaseType.MySql);
            var database = new Database(databaseType, _connectionString);
            var connection = database.GetConnection();
            var items = await connection.ExecuteScalarAsync<int>(sql);
            return items > 0;
        }
        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public async Task<bool> UpdateAsync(Query query)
        {
            return await _repository.UpdateAsync(query) > 0;
        }

        public async Task<bool> UpdateAsync(Middle middle)
        {
            return await _repository.UpdateAsync(middle);
        }

        public async Task<IEnumerable<Middle>> FindAsync(Query query)
        {
            return await _repository.GetAllAsync(query);
        }

        public async Task<bool> DeleteAsync(Query query)
        {
            return await _repository.DeleteAsync(query) > 0;
        }


        public async Task<bool> DeleteAsync(int middleId, int folderTypeId)
        {
            return await _repository.DeleteAsync(Q.Where(nameof(Entity.Middle.Middle.MiddleId), middleId).Where(nameof(Entity.Middle.Middle.FolderType), folderTypeId)) > 0;
        }
        public async Task<Middle> GetMiddleAsync(Query query)
        {
            return await _repository.GetAsync(query);
        }
        public async Task<Middle> GetMiddleAsync(int id)
        {
            return await _repository.GetAsync(id);
        }
        /// <summary>
        /// 获取下级数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<IEnumerable<Middle>> GetMiddleChildrenAsync(int id)
        {
            return await _repository.GetAllAsync(Q.Where(nameof(Entity.Middle.Middle.ParentId), id));
        }
        /// <summary>
        /// 设置排序
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> SetSortAsync(MiddleSortRequest request)
        {
            //获取第一个
            var middleFirst = await _repository.GetAsync(request.MiddleIdFirst);
            //获取第二个数据
            var middleSecond = await _repository.GetAsync(request.MiddleIdSecond);
            var databaseType = _databaseTypeStr.ToEnum<DatabaseType>(DatabaseType.MySql);
            var database = new Database(databaseType, _connectionString);
            var connection = database.GetConnection();
            if (middleFirst.Sort < middleSecond.Sort)
            {
                //修改第一个排序
                await _repository.UpdateAsync(Q.Set(nameof(Middle.Sort), middleSecond.Sort)
                    .Where(nameof(Middle.Id), request.MiddleIdFirst));
                int sort = middleSecond.Sort;
                var sql =
                    $"update tede_middle set Sort=Sort-1 where UserId={middleFirst.UserId} and FolderType={middleFirst.FolderType} and Sort<={sort} and Id not in({middleFirst.Id}) and id>0";
                return await connection.ExecuteAsync(sql) > 0;
            }
            else
            {
                //修改第一个排序
                await _repository.UpdateAsync(Q.Set(nameof(Middle.Sort), middleSecond.Sort)
                    .Where(nameof(Middle.Id), request.MiddleIdFirst));
                int sort = middleSecond.Sort;
                var sql =
                    $"update tede_middle set Sort=Sort+1 where UserId={middleFirst.UserId} and FolderType={middleFirst.FolderType} and Sort<={sort} and Id not in({middleFirst.Id}) and id>0";
                return await connection.ExecuteAsync(sql) > 0;
            }
        }

        /// <summary>
        /// 设置置顶
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> SetTopAsync(int id)
        {
            var middle = await _repository.GetAsync(id);
            if (middle == null)
                throw new BusinessException("数据不存在");
            var databaseType = _databaseTypeStr.ToEnum<DatabaseType>(DatabaseType.MySql);
            var database = new Database(databaseType, _connectionString);
            var connection = database.GetConnection();
            return await _repository.UpdateAsync(Q.Set(nameof(Middle.IsTop), !middle.IsTop).Where(nameof(Middle.Id), id)) > 0;
            // var isTop = middle.IsTop == true ? 0 : 1;
            // var sql = $"update tede_middle set IsTop={isTop} where id={id}";
            // return await connection.ExecuteAsync(sql) > 0;
        }

        public async Task<bool> DeleteAsync(NoticeDeRequest request)
        {
            if (request.IsDelete)
                return await _repository.DeleteAsync(Q.WhereIn(nameof(Middle.Id), request.MiddleIds).Where(nameof(Middle.FolderType), request.FolderType)) > 0;
            return await _repository.UpdateAsync(Q.WhereIn(nameof(Middle.Id), request.MiddleIds).Where(nameof(Middle.FolderType), request.FolderType).Set(nameof(Middle.IsDelete), true)) > 0;
        }
        /// <summary>
        /// 恢复删除
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> RecoverDeleteAsync(NoticeDeRequest request)
        {
            return await _repository.UpdateAsync(Q.Set(nameof(Middle.IsDelete), false)
                       .WhereIn(nameof(Middle.Id), request.MiddleIds)) > 0;
        }
        /// <summary>
        /// 阅读
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> ReadAsync(int id)
        {
            return await _repository.UpdateAsync(Q.Set(nameof(Middle.IsRead), true)
                       .Where(nameof(Middle.Id), id)) > 0;
        }

        /// <summary>
        /// 修改文件夹名称
        /// </summary>
        /// <returns></returns>
        public async Task<bool> UpdateFolderNameAsync(MiddleFolderNameRequest request)
        {
            return await _repository.UpdateAsync(Q.Set(nameof(Middle.FolderName), request.FolderName)
                       .Where(nameof(Middle.Id), request.Id)) > 0;
        }

        public async Task<bool> IsFolderAsync(int parentId)
        {
            return await _repository.CountAsync(Q.Where(nameof(Middle.ParentId), parentId).Where(nameof(Middle.IsDelete), false).Where(nameof(Middle.AttributeValue), 2)) > 0;
        }



        /// <summary>
        /// 根据用户ID文件夹ID查询小组数量
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="groupFolderId"></param>
        /// <param name="folderTypeId"></param>
        /// <returns></returns>
        public async Task<int> FindGroupCountAsync(int userId, int groupFolderId, int folderTypeId)
        {
            return await _repository.CountAsync(Q.Where(nameof(Middle.UserId), userId)
                .Where(nameof(Middle.Id), groupFolderId).Where(nameof(Middle.FolderType), folderTypeId));
        }

        public async Task<int> CountAsync(Query query)
        {
            return await _repository.CountAsync(query);
        }

        public async Task<IEnumerable<Middle>> GetAllAsync(SqlKata.Query query)
        {
            return await _repository.GetAllAsync(query);
        }

        public async Task<IEnumerable<Middle>> FindAsync(InboxSearchRequest request)
        {
            var query = new SqlKata.Query();
            if (request.Type > 0)
            {
                query.Where(nameof(Middle.FolderType), request.Type);
            }
            else
            {
                var listType = new List<int> { GxPress.EnumConst.FolderTypeConst.Notice.GetHashCode(), GxPress.EnumConst.FolderTypeConst.Missive.GetHashCode(), GxPress.EnumConst.FolderTypeConst.Submitted.GetHashCode(), GxPress.EnumConst.FolderTypeConst.Approval.GetHashCode(), GxPress.EnumConst.FolderTypeConst.Cc.GetHashCode() };
                query.WhereIn(nameof(Middle.FolderType), listType);
            }
            if (!string.IsNullOrWhiteSpace(request.KeyWord))
            {
                query.OrWhere(nameof(Middle.TitleLong), request.KeyWord);
                query.OrWhere(nameof(Middle.AddressUserComplete), request.KeyWord);
                query.OrWhere(nameof(Middle.CcUserComplete), request.KeyWord);
                query.OrWhere(nameof(Middle.Content), request.KeyWord);
            }
            query.Where(nameof(Middle.UserId), request.UserId);
            return await _repository.GetAllAsync(query.Select("Id", "Guid", "CreatedDate", "LastModifiedDate", "FolderName", "FolderType", "IsTop", "RoleId", "Sort", "MiddleId", "ParentId", "UserId", "MiddleSonId", "IsRead", "NoticeAddresseeType", "IsAdmin", "IsDelete", "AttributeValue", "IsDefault", "IsUpload", "Title", "AddressUser", "CcUser"));
        }
    }
}