using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using GxPress.Common.AppOptions;
using GxPress.Common.Exceptions;
using GxPress.Common.Tools;
using GxPress.Entity;
using GxPress.Repository.Interface;
using GxPress.Request.Role;
using GxPress.Result.Role;
using Microsoft.Extensions.Options;
using Datory;

namespace GxPress.Repository.Implement
{
    public class RoleRepository : IRoleRepository
    {
        private readonly Repository<Role> _repository;

        public RoleRepository(IOptionsMonitor<DatabaseOptions> dbOptionsAccessor)
        {
            var databaseType = StringUtils.ToEnum<DatabaseType>(dbOptionsAccessor.CurrentValue.DatabaseType, DatabaseType.MySql);
            var database = new Database(databaseType, dbOptionsAccessor.CurrentValue.ConnectionString);
            _repository = new Repository<Role>(database);
        }

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

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

        public async Task<bool> IsNameExistsAsync(string name)
        {
            return await _repository.ExistsAsync(Q.Where(nameof(Role.Name), name));
        }

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

        public async Task<string> GetNameAsync(int id)
        {
            if (id <= 0) return string.Empty;

            return await _repository.GetAsync<string>(Q
                .Select(nameof(Role.Name))
                .Where(nameof(Role.Id), id)
            );
        }

        public async Task<IEnumerable<Role>> GetListAsync(int groupId)
        {
            return await _repository.GetAllAsync(Q.Where(nameof(Role.GroupId), groupId).OrderBy(nameof(Role.Sort)));
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<RoleDetailResult> AddAsync(RoleAddRequest request)
        {
            var role = new Role
            {
                GroupId = request.GroupId,
                Name = request.Name,
                Sort = request.Sort
            };
            role.Id = await InsertAsync(role);

            return new RoleDetailResult
            {
                Id = role.Id,
                Name = role.Name,
                GroupId = role.GroupId,
                Sort = role.Sort
            };
        }

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

            role.Name = request.Name;
            role.GroupId = request.GroupId;
            role.Sort = request.Sort;
            return await _repository.UpdateAsync(role);
        }

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

            return await _repository.DeleteAsync(id);
        }

        /// <summary>
        /// 详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<RoleDetailResult> GetDetailAsync(int id)
        {
            var role = await GetAsync(id);
            if (role == null) throw new BusinessException("该角色不存在");

            return new RoleDetailResult
            {
                Id = role.Id,
                Name = role.Name,
                GroupId = role.GroupId
            };
        }

        /// <summary>
        /// 列表
        /// </summary>
        /// <param name="groupId"></param>
        /// <returns></returns>
        public async Task<List<RoleDetailResult>> GetDetailListAsync(int groupId)
        {
            var list = await GetListAsync(groupId);

            var result = list.Select(item => new RoleDetailResult
            {
                Id = item.Id,
                Name = item.Name,
                GroupId = item.GroupId,
                Sort = item.Sort
            }).ToList();
            return result;
        }
    }
}