using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using GxPress.Common.AppOptions;
using GxPress.Common.Encrypt;
using GxPress.Common.Exceptions;
using GxPress.Common.Page;
using GxPress.Common.Tools;
using GxPress.Entity;
using GxPress.Repository.Interface;
using GxPress.Request.Admin;
using GxPress.Result.Admin;
using Microsoft.Extensions.Options;
using SqlKata;
using Datory;
using Microsoft.Extensions.Caching.Distributed;
using GxPress.Common.Extensions;

namespace GxPress.Repository.Implement
{
    public class AdminRepository : IAdminRepository
    {
        private readonly Repository<Admin> _repository;
        private readonly IMapper _mapper;
        private readonly IDistributedCache _cache;

        public AdminRepository(IOptionsMonitor<DatabaseOptions> dbOptionsAccessor, IMapper mapper, IDistributedCache cache)
        {
            var databaseType = StringUtils.ToEnum<DatabaseType>(dbOptionsAccessor.CurrentValue.DatabaseType, DatabaseType.MySql);
            var database = new Database(databaseType, dbOptionsAccessor.CurrentValue.ConnectionString);
            _repository = new Repository<Admin>(database);
            _mapper = mapper;
            _cache = cache;
        }

        public IDatabase Database => _repository.Database;
        public string TableName => _repository.TableName;
        public List<TableColumn> TableColumns => _repository.TableColumns;

        //public async Task<IEnumerable<AdminPageResult>> GetPagedList(AdminPageSearchRequest request)
        //{
        //    var fieldSql = @"Id,Account,Name,Cdt";
        //    var fromSql = @"Admin";
        //    var whereSql = new StringBuilder("where 1=1");
        //    var queryParam = new DynamicParameters();

        //    if (!string.IsNullOrEmpty(request.Keyword))
        //    {
        //        whereSql.Append("and (Account like @keyword or Name like @keyword)");
        //        queryParam.Add("keyword", "%" + request.Keyword + "%");
        //    }

        //    var result = await _repository.GetAllAsync<AdminPageResult>();
        //    return result;
        //}
        public async Task<Admin> GetByAccountAsync(string account)
        {
            return await _repository.GetAsync(Q.Where(nameof(Admin.Account), account));
        }

        public async Task<bool> ExistsAsync(string account)
        {
            return await _repository.ExistsAsync(Q.Where(nameof(Admin.Account), account));
        }

        public async Task<Admin> GetAsync(int id)
        {
            return await _repository.GetAsync(id);
        }

        public async Task<int> InsertAsync(Admin admin)
        {
            return await _repository.InsertAsync(admin);
        }

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

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

        /// <summary>
        /// Set the limit and offset for a given page.
        /// </summary>
        /// <param name="page"></param>
        /// <param name="perPage"></param>
        /// <returns></returns>
        public async Task<IEnumerable<Admin>> GetPageListAsync(int page, int perPage)
        {
            return await _repository.GetAllAsync(Q.ForPage(page, perPage)); 

        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<AdminSignInResult> SignInAsync(AdminSignInRequest request)
        {
            var key = $"captcha:{request.Guid.ToString()}";

            var captcha = await _cache.GetStringAsync(key);
            if (!captcha.Equals(request.Captcha, StringComparison.OrdinalIgnoreCase))
                throw new BusinessException("验证码错误");

            var admin = await GetByAccountAsync(request.Account);
            if (admin == null) throw new BusinessException("不存在该账号");

            var pwd = EncryptProvider.Md5($"{request.Password}{request.Account}");
            if (admin.Password != pwd) throw new BusinessException("密码错误");
            //新增获取菜单数据
            var result = new AdminSignInResult { AdminId = admin.Id,Menus = StringUtils.StringCollectionToStringList(admin.Menus).ToList(),Name = admin.Name};
            return result;
        }

        /// <summary>
        /// 注册
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<int> SignUpAsync(AdminSignUpRequest request)
        {
            var accountExist = await ExistsAsync(request.Account);
            if (accountExist) throw new BusinessException("已存在该账号");

            var admin = new Admin
            {
                Account = request.Account,
                Name = request.Name,
                Password = EncryptProvider.Md5($"{request.Password}{request.Account}"),
                Phone = request.Phone,
                Email = request.Email,
                Sex = request.Sex
            };
            var result = await InsertAsync(admin);
            return result;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> DeleteAsync(int id)
        {
            var admin = await GetAsync(id);
            if (admin == null) throw new BusinessException("不存在该账号");

            return await _repository.DeleteAsync(id);
        }

        /// <summary>
        /// 分页列表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<PagedList<AdminPageResult>> GetPagedList(AdminPageSearchRequest request)
        {
            var pagedList = new PagedList<AdminPageResult>
            {
                Total = await GetCountAsync()
            };
            var list = await GetPageListAsync(request.Page, request.PerPage);
            var items = list.Select(user => _mapper.Map<AdminPageResult>(user)).ToList();
            pagedList.Items = items;
            return pagedList;
        }

        /// <summary>
        /// 获取详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<AdminDetailResult> GetDetailAsync(int id)
        {
            var admin = await GetAsync(id);
            if (admin == null) throw new BusinessException("该用户不存在");
            return new AdminDetailResult
            {
                Id = admin.Id,
                Account = admin.Account,
                Name = admin.Name,
                Phone = admin.Phone,
                Email = admin.Email,
                Sex = admin.Sex,
                Menus = admin.Menus,
            };
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="id"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> UpdateAsync(int id, Admin request)
        {
            var admin = await GetAsync(id);
            if (admin == null) throw new BusinessException("该用户不存在");

            //var pwd = EncryptProvider.Md5($"{request.OldPassword}{admin.Account}");
            //if (pwd != admin.Password) throw new BusinessException("旧密码错误");

            //admin.Name = request.Name;
            //admin.Password = EncryptProvider.Md5($"{request.NewPassword}{admin.Account}");
            request.Id=id;
            request.Password = admin.Password;
            request.CreatedDate = admin.CreatedDate;
            return await UpdateAsync(request);
        }
        /// <summary>
        /// 修改根据条件修改
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> UpdateQAsync(Admin request)
        {
            return await _repository.UpdateAsync(Q.Set(nameof(Admin.Menus), request.Menus).Where(nameof(Admin.Id), request.Id)) >
                   0;
        }

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<bool> UpdatePassWord(AdminUpdatePassWordRequest request)
        {
            //获取用户
            var admin = await GetAsync(request.Id);
            if (admin == null) throw new BusinessException("该用户不存在");
            //验证旧密码
            var pwd = EncryptProvider.Md5($"{request.OldPassword}{request.Account}");
            if (pwd != admin.Password) throw new BusinessException("旧密码错误");
            admin.Password = EncryptProvider.Md5($"{request.NewPassword}{admin.Account}");
            //修改
            return await _repository.UpdateAsync(Q.Set(nameof(Admin.Password), admin.Password)
                       .Where(nameof(admin.Id), request.Id)) > 0;
        }

        public async Task<bool> AdminUpdatePassWord(AdminUpdatePassWordRequest request)
        {
            //获取用户
            var admin = await GetAsync(request.Id);
            if (admin == null) throw new BusinessException("该用户不存在");
            //生成密码
            var pwd = EncryptProvider.Md5($"{request.NewPassword}{admin.Account}");
            //修改
            return await _repository.UpdateAsync(Q.Set(nameof(Admin.Password), pwd)
                       .Where(nameof(Admin.Id), request.Id)) > 0;
        }
    }
}