using DocumentFormat.OpenXml.ExtendedProperties;
using Fw.Utility.UnifyResponse;
using Hotline.Application.Users;
using Hotline.Caching.Interfaces;
using Hotline.Identity.Roles;
using Hotline.Permissions;
using Hotline.Repository.SqlSugar;
using Hotline.Repository.SqlSugar.Extensions;
using Hotline.SeedData;
using Hotline.Settings;
using Hotline.Share.Dtos;
using Hotline.Share.Dtos.Roles;
using Hotline.Share.Enums.Identity;
using Hotline.Share.Enums.Order;
using Hotline.Share.Enums.Settings;
using Hotline.Share.Enums.User;
using Hotline.Share.Tools;
using MapsterMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using SqlSugar;
using XF.Domain.Authentications;
using XF.Domain.Exceptions;
using XF.Domain.Options;
using XF.Domain.Repository;
using XF.Utility.EnumExtensions;

namespace Hotline.Api.Controllers;

/// <summary>
/// 角色权限管理相关接口
/// </summary>
public class RoleController : BaseController
{
    private readonly IRepository<Role> _roleRepository;
    private readonly ISystemAuthorityRepository _systemAuthorityRepository;
    private readonly ISystemDataAuthorityRepository _systemDataAuthorityRepository;
    private readonly IRepository<TableAccessLevel> _tableAccessLevelRepository;
    private readonly IMapper _mapper;
    private readonly ITableAccessLevelCacheManager _tableAccessLevelCacheManager;
    private readonly IRolePermissionsCacheManager _rolePermissionsCacheManager;
    private readonly IOptions<IdentityConfiguration> _identityConfigurationAccessor;
    private readonly IRepository<SystemDataTable> _systemDataTableRepository;
    private readonly ISessionContext _sessionContext;
    private readonly IRoleApplication _roleApplication;

    public RoleController(
        IRepository<Role> roleRepository,
        ISystemAuthorityRepository systemAuthorityRepository,
        ISystemDataAuthorityRepository systemDataAuthorityRepository,
        IRepository<TableAccessLevel> tableAccessLevelRepository,
        ITableAccessLevelCacheManager tableAccessLevelCacheManager,
        IRolePermissionsCacheManager rolePermissionsCacheManager,
        IMapper mapper,
        IOptions<IdentityConfiguration> identityConfigurationAccessor,
        IRepository<SystemDataTable> systemDataTableRepository,
        ISessionContext sessionContext,
        IRoleApplication roleApplication)
    {
        _roleRepository = roleRepository;
        _systemAuthorityRepository = systemAuthorityRepository;
        _systemDataAuthorityRepository = systemDataAuthorityRepository;
        _tableAccessLevelRepository = tableAccessLevelRepository;
        _tableAccessLevelCacheManager = tableAccessLevelCacheManager;
        _rolePermissionsCacheManager = rolePermissionsCacheManager;
        _mapper = mapper;
        _identityConfigurationAccessor = identityConfigurationAccessor;
        _systemDataTableRepository = systemDataTableRepository;
        _sessionContext = sessionContext;
        _roleApplication = roleApplication;
    }

    /// <summary>
    /// 分页查询角色
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    [HttpGet("paged")]
    public async Task<PagedDto<RoleDto>> GetRuleItems([FromQuery] QueryRolesPagedDto dto)
    {
		var (total, items) =  await _roleApplication.GetRuleItems(dto).ToPagedListAsync(dto);
		return new PagedDto<RoleDto>(total, _mapper.Map<IReadOnlyList<RoleDto>>(items)); 
    }

    /// <summary>
    /// 新增角色
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    [HttpPost]
    public async Task<string> Add([FromBody] AddRoleDto dto)
    {
        var jwtOption = _identityConfigurationAccessor.Value.Jwt;
        var clientId = jwtOption.Issuer;
        if (string.IsNullOrEmpty(clientId))
            throw new UserFriendlyException("jwt.Issuer未配置");

        if (string.IsNullOrEmpty(dto.Name))
            throw UserFriendlyException.SameMessage("角色编码不能为空");

        var exists = await _roleRepository.Queryable(includeDeleted: true)
            .AnyAsync(d => d.ClientId == clientId && d.Name == dto.Name);
        if (exists)
            throw UserFriendlyException.SameMessage("角色编码重复");

        var role = _mapper.Map<Role>(dto);
        role.ClientId = clientId;
        return await _roleRepository.AddAsync(role, HttpContext.RequestAborted);
    }

    /// <summary>
    /// 删除角色
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpDelete("{id}")]
    public async Task Remove(string id)
    {
        var role = await _roleRepository.Queryable()
            .Includes(d => d.Accounts)
            .FirstAsync(d => d.Id == id);

        role.Accounts.Clear();
        await _roleRepository.UpdateNav(role)
            .Include(d => d.Accounts)
            .ExecuteCommandAsync();

        await _systemAuthorityRepository.RemoveAsync(id);
        await _systemDataAuthorityRepository.RemoveAsync(x => x.RoleId == id);

        await _roleRepository.RemoveAsync(id, true, HttpContext.RequestAborted);
    }

    /// <summary>
    /// 更新角色
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    [HttpPut]
    public async Task Update([FromBody] UpdateRoleDto dto)
    {
        var role = await _roleRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
        if (role == null) throw new UserFriendlyException("无效角色编号");
        _mapper.Map(dto, role);
        await _roleRepository.UpdateAsync(role, HttpContext.RequestAborted);
    }


    /// <summary>
    /// 角色基础数据
    /// </summary>
    /// <returns></returns>
    [HttpGet("role/basedata")]
    public object RoleBaseData()
    {
        return new
        {
            RoleType = EnumExts.GetDescriptions<ERoleType>(),
        };
    }


    #region 应用权限管理

    /// <summary>
    /// 分配权限
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    [HttpPost("allocationauthority")]
    public async Task AllocationAuthority(RoleAuthorityDto dto)
    {
        //判断是否存在，如果存在就做更新
        var model = await _systemAuthorityRepository.GetAsync(x => x.RoleId == dto.RoleId);
        if (model is null)
        {
            model = _mapper.Map<SystemAuthority>(dto);
            await _systemAuthorityRepository.AddAsync(model);
        }
        else
        {
            _mapper.Map(dto, model);
            await _systemAuthorityRepository.UpdateAsync(model);
        }
        _rolePermissionsCacheManager.RemovePermissions(dto.RoleCode);
    }

    /// <summary>
    /// 获取角色权限
    /// </summary>
    /// <param name="roleid"></param>
    /// <returns></returns>
    [HttpGet("getauthority")]
    public async Task<SystemAuthority?> GetAuthority(string roleid)
    {
        return await _systemAuthorityRepository.GetAsync(x => x.RoleId == roleid, HttpContext.RequestAborted);
    }

    /// <summary>
    /// 查询角色的按钮权限码
    /// </summary>
    /// <param name="roleId"></param>
    /// <returns></returns>
    [HttpGet("permissions-button")]
    public async Task<IReadOnlyList<string>> GetButtonPermissions(string roleId)
    {
        var rolePermission = await _systemAuthorityRepository.GetAsync(x => x.RoleId == roleId, HttpContext.RequestAborted);
        if (rolePermission is null)
            return new List<string>();
        return rolePermission.SystemMenuArr.Where(d => d.Type is EMenuType.Button).Select(d => d.Code).ToList();
    }

    #endregion

    #region 数据权限管理

    /// <summary>
    /// 获取数据表
    /// </summary>
    /// <returns></returns>
    [HttpGet("datatable-list")]
    [Obsolete]
    public async Task<IReadOnlyList<SystemDataTable>> GetDataTable()
    {
        return await _systemDataTableRepository.Queryable().ToListAsync();
    }

    /// <summary>
    /// 获取数据表
    /// </summary>
    [HttpGet("tables")]
    public IReadOnlyList<KeyValuePair<string, string>> GetTables([FromServices] ISugarUnitOfWork<HotlineDbContext> uow)
    {
        var tables = uow.Db.DbMaintenance.GetTableInfoList(false)
            .Where(d => !string.IsNullOrEmpty(d.Description))
            .Select(d => new KeyValuePair<string, string>(d.Name, d.Description))
            .ToList();

        return tables;
    }

    /// <summary>
    /// 新增数据权限
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    [HttpPost("add-data-authority")]
    [Obsolete]
    public async Task AddDataAuthority([FromBody] AddAccessLevelDto dto)
    {
        var dataAuthority = _mapper.Map<SystemDataAuthority>(dto);
        await _systemDataAuthorityRepository.AddAsync(dataAuthority);
    }

    /// <summary>
    /// 新增数据权限
    /// </summary>
    [HttpPost("accesslevel")]
    public async Task<string> AddAccessLevel([FromBody] AddAccessLevelDto dto)
    {
        var access = _mapper.Map<TableAccessLevel>(dto);
        await _tableAccessLevelRepository.AddAsync(access, HttpContext.RequestAborted);
        _tableAccessLevelCacheManager.Reload();
        return access.Id;
    }

    /// <summary>
    /// 修改数据权限
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    [HttpPost("update-data-authority")]
    [Obsolete]
    public async Task UpdateDataAuthority([FromBody] UpdateDataAuthorityDto dto)
    {
        var entity = await _systemDataAuthorityRepository.GetAsync(x => x.Id == dto.Id, HttpContext.RequestAborted);
        if (entity is null)
            throw UserFriendlyException.SameMessage("无效数据");

        entity.AuthorityType = dto.AccessLevel;
        await _systemDataAuthorityRepository.UpdateAsync(entity, HttpContext.RequestAborted);
    }

    /// <summary>
    /// 修改数据权限
    /// </summary>
    [HttpPut("accesslevel")]
    public async Task UpdateAccessLevel([FromBody] UpdateDataAuthorityDto dto)
    {
        var access = await _tableAccessLevelRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
        if (access is null)
            throw UserFriendlyException.SameMessage("无效accesslevel编号");
        _mapper.Map(dto, access);
        await _tableAccessLevelRepository.UpdateAsync(access, HttpContext.RequestAborted);
        _tableAccessLevelCacheManager.Reload();
    }

    /// <summary>
    /// 删除数据权限
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpDelete("remove-data-authority/{id}")]
    [Obsolete]
    public async Task RemoveDataAuthority(string id)
    {
        var entity = await _systemDataAuthorityRepository.GetAsync(id, HttpContext.RequestAborted);
        if (entity is null)
            throw UserFriendlyException.SameMessage("无效数据");

        await _systemDataAuthorityRepository.RemoveAsync(id);
    }

    /// <summary>
    /// 删除数据权限
    /// </summary>
    [HttpDelete("accesslevel/{id}")]
    public async Task RemoveAccessLevel(string id)
    {
        await _tableAccessLevelRepository.RemoveAsync(id, cancellationToken: HttpContext.RequestAborted);
        _tableAccessLevelCacheManager.Reload();
    }

    /// <summary>
    /// 获取角色所有数据权限设置
    /// </summary>
    /// <param name="roleid"></param>
    /// <returns></returns>
    [HttpGet("getdataauthoritybyrole")]
    [Obsolete]
    public async Task<IReadOnlyList<SystemDataAuthority>> GetDataAuthorityByRole(string roleid)
    {
        return await _systemDataAuthorityRepository.Queryable().Where(x => x.RoleId == roleid).Includes(x => x.Table).Includes(x => x.Role).ToListAsync();
    }


    /// <summary>
    /// 获取角色所有数据权限设置
    /// </summary>
    [HttpGet("{roleId}/accesslevels")]
    public async Task<IReadOnlyList<TableAccessLevel>> GetAccessLevels(string roleId)
    {
        return await _tableAccessLevelRepository.Queryable()
            .Where(d => d.RoleId == roleId)
            .ToListAsync();
    }

    [HttpGet("base-data")]
    public object BaseData()
    {
        return new
        {
            AccessLevelOptions = EnumExts.GetDescriptions<ETableAccessLevel>()
        };
    }

    #endregion

    #region private

    private void CheckHttpRequestSuccess(ApiResponse response, string msg)
    {
        if (response == null || !response.IsSuccess)
            throw new UserFriendlyException($"identity service request failed: {msg}");
    }

    #endregion
}