using HoneyBox.Admin.Data;
using HoneyBox.Admin.Entities;
using HoneyBox.Admin.Models.Common;
using HoneyBox.Admin.Models.Role;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace HoneyBox.Admin.Services;

/// <summary>
/// 角色服务实现
/// </summary>
public class RoleService : IRoleService
{
    private readonly AdminDbContext _dbContext;
    private readonly ILogger<RoleService> _logger;

    public RoleService(AdminDbContext dbContext, ILogger<RoleService> logger)
    {
        _dbContext = dbContext;
        _logger = logger;
    }

    /// <inheritdoc />
    public async Task<PagedResult<RoleDto>> GetListAsync(RoleQueryRequest request)
    {
        var query = _dbContext.Roles.AsQueryable();

        // 名称筛选
        if (!string.IsNullOrWhiteSpace(request.Name))
        {
            query = query.Where(r => r.Name.Contains(request.Name));
        }

        // 编码筛选
        if (!string.IsNullOrWhiteSpace(request.Code))
        {
            query = query.Where(r => r.Code.Contains(request.Code));
        }

        // 状态筛选
        if (request.Status.HasValue)
        {
            query = query.Where(r => r.Status == request.Status.Value);
        }

        var total = await query.CountAsync();

        var list = await query
            .OrderBy(r => r.SortOrder)
            .ThenByDescending(r => r.CreatedAt)
            .Skip((request.Page - 1) * request.PageSize)
            .Take(request.PageSize)
            .Select(r => new RoleDto
            {
                Id = r.Id,
                Name = r.Name,
                Code = r.Code,
                Description = r.Description,
                SortOrder = r.SortOrder,
                Status = r.Status,
                IsSystem = r.IsSystem,
                CreatedAt = r.CreatedAt,
                UpdatedAt = r.UpdatedAt
            })
            .ToListAsync();

        return new PagedResult<RoleDto>
        {
            List = list,
            Total = total,
            Page = request.Page,
            PageSize = request.PageSize
        };
    }


    /// <inheritdoc />
    public async Task<RoleDto> GetByIdAsync(long id)
    {
        var role = await _dbContext.Roles
            .Include(r => r.RoleMenus)
            .Include(r => r.RolePermissions)
            .FirstOrDefaultAsync(r => r.Id == id);

        if (role == null)
        {
            throw new AdminException(AdminErrorCodes.RoleNotFound, "角色不存在");
        }

        return new RoleDto
        {
            Id = role.Id,
            Name = role.Name,
            Code = role.Code,
            Description = role.Description,
            SortOrder = role.SortOrder,
            Status = role.Status,
            IsSystem = role.IsSystem,
            CreatedAt = role.CreatedAt,
            UpdatedAt = role.UpdatedAt,
            MenuIds = role.RoleMenus.Select(rm => rm.MenuId).ToList(),
            PermissionIds = role.RolePermissions.Select(rp => rp.PermissionId).ToList()
        };
    }

    /// <inheritdoc />
    public async Task<long> CreateAsync(CreateRoleRequest request)
    {
        // 检查编码是否重复
        var codeExists = await _dbContext.Roles.AnyAsync(r => r.Code == request.Code);
        if (codeExists)
        {
            throw new AdminException(AdminErrorCodes.DuplicateRoleCode, "角色编码已存在");
        }

        var role = new Role
        {
            Name = request.Name,
            Code = request.Code,
            Description = request.Description,
            SortOrder = request.SortOrder,
            Status = request.Status,
            IsSystem = false,
            CreatedAt = DateTime.Now
        };

        _dbContext.Roles.Add(role);
        await _dbContext.SaveChangesAsync();

        _logger.LogInformation("创建角色成功: {RoleId} - {RoleName}", role.Id, role.Name);
        return role.Id;
    }

    /// <inheritdoc />
    public async Task UpdateAsync(long id, UpdateRoleRequest request)
    {
        var role = await _dbContext.Roles.FindAsync(id);
        if (role == null)
        {
            throw new AdminException(AdminErrorCodes.RoleNotFound, "角色不存在");
        }

        // 检查编码是否重复（排除自己）
        var codeExists = await _dbContext.Roles.AnyAsync(r => r.Code == request.Code && r.Id != id);
        if (codeExists)
        {
            throw new AdminException(AdminErrorCodes.DuplicateRoleCode, "角色编码已存在");
        }

        role.Name = request.Name;
        role.Code = request.Code;
        role.Description = request.Description;
        role.SortOrder = request.SortOrder;
        role.Status = request.Status;
        role.UpdatedAt = DateTime.Now;

        await _dbContext.SaveChangesAsync();
        _logger.LogInformation("更新角色成功: {RoleId} - {RoleName}", role.Id, role.Name);
    }

    /// <inheritdoc />
    public async Task DeleteAsync(long id)
    {
        var role = await _dbContext.Roles.FindAsync(id);
        if (role == null)
        {
            throw new AdminException(AdminErrorCodes.RoleNotFound, "角色不存在");
        }

        // 系统角色不能删除
        if (role.IsSystem)
        {
            throw new AdminException(AdminErrorCodes.CannotDeleteSystemRole, "系统角色不能删除");
        }

        // 删除关联数据
        var roleMenus = await _dbContext.RoleMenus.Where(rm => rm.RoleId == id).ToListAsync();
        _dbContext.RoleMenus.RemoveRange(roleMenus);

        var rolePermissions = await _dbContext.RolePermissions.Where(rp => rp.RoleId == id).ToListAsync();
        _dbContext.RolePermissions.RemoveRange(rolePermissions);

        var userRoles = await _dbContext.AdminUserRoles.Where(ur => ur.RoleId == id).ToListAsync();
        _dbContext.AdminUserRoles.RemoveRange(userRoles);

        _dbContext.Roles.Remove(role);
        await _dbContext.SaveChangesAsync();

        _logger.LogInformation("删除角色成功: {RoleId} - {RoleName}", id, role.Name);
    }

    /// <inheritdoc />
    public async Task<List<long>> GetMenuIdsAsync(long roleId)
    {
        var role = await _dbContext.Roles.FindAsync(roleId);
        if (role == null)
        {
            throw new AdminException(AdminErrorCodes.RoleNotFound, "角色不存在");
        }

        return await _dbContext.RoleMenus
            .Where(rm => rm.RoleId == roleId)
            .Select(rm => rm.MenuId)
            .ToListAsync();
    }

    /// <inheritdoc />
    public async Task AssignMenusAsync(long roleId, List<long> menuIds)
    {
        var role = await _dbContext.Roles.FindAsync(roleId);
        if (role == null)
        {
            throw new AdminException(AdminErrorCodes.RoleNotFound, "角色不存在");
        }

        // 删除现有关联
        var existingMenus = await _dbContext.RoleMenus.Where(rm => rm.RoleId == roleId).ToListAsync();
        _dbContext.RoleMenus.RemoveRange(existingMenus);

        // 添加新关联
        if (menuIds.Any())
        {
            var newMenus = menuIds.Distinct().Select(menuId => new RoleMenu
            {
                RoleId = roleId,
                MenuId = menuId
            });
            _dbContext.RoleMenus.AddRange(newMenus);
        }

        await _dbContext.SaveChangesAsync();
        _logger.LogInformation("角色 {RoleId} 分配菜单成功，菜单数量: {Count}", roleId, menuIds.Count);
    }

    /// <inheritdoc />
    public async Task<List<string>> GetPermissionCodesAsync(long roleId)
    {
        var role = await _dbContext.Roles.FindAsync(roleId);
        if (role == null)
        {
            throw new AdminException(AdminErrorCodes.RoleNotFound, "角色不存在");
        }

        return await _dbContext.RolePermissions
            .Where(rp => rp.RoleId == roleId)
            .Join(_dbContext.Permissions, rp => rp.PermissionId, p => p.Id, (rp, p) => p.Code)
            .ToListAsync();
    }

    /// <inheritdoc />
    public async Task AssignPermissionsAsync(long roleId, List<string> permissionCodes)
    {
        var role = await _dbContext.Roles.FindAsync(roleId);
        if (role == null)
        {
            throw new AdminException(AdminErrorCodes.RoleNotFound, "角色不存在");
        }

        // 删除现有关联
        var existingPermissions = await _dbContext.RolePermissions.Where(rp => rp.RoleId == roleId).ToListAsync();
        _dbContext.RolePermissions.RemoveRange(existingPermissions);

        // 添加新关联
        if (permissionCodes.Any())
        {
            // 根据权限编码获取权限ID
            var permissions = await _dbContext.Permissions
                .Where(p => permissionCodes.Contains(p.Code))
                .ToListAsync();

            var newPermissions = permissions.Select(p => new RolePermission
            {
                RoleId = roleId,
                PermissionId = p.Id
            });
            _dbContext.RolePermissions.AddRange(newPermissions);
        }

        await _dbContext.SaveChangesAsync();
        _logger.LogInformation("角色 {RoleId} 分配权限成功，权限数量: {Count}", roleId, permissionCodes.Count);
    }

    /// <inheritdoc />
    public async Task<List<RoleDto>> GetAllAsync()
    {
        return await _dbContext.Roles
            .Where(r => r.Status == 1)
            .OrderBy(r => r.SortOrder)
            .Select(r => new RoleDto
            {
                Id = r.Id,
                Name = r.Name,
                Code = r.Code,
                Description = r.Description,
                SortOrder = r.SortOrder,
                Status = r.Status,
                IsSystem = r.IsSystem,
                CreatedAt = r.CreatedAt,
                UpdatedAt = r.UpdatedAt
            })
            .ToListAsync();
    }
}
