using System.Collections.Concurrent;
using HoneyBox.Admin.Data;
using HoneyBox.Admin.Entities;
using HoneyBox.Admin.Models.Permission;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace HoneyBox.Admin.Services;

/// <summary>
/// 权限服务实现
/// </summary>
public class PermissionService : IPermissionService
{
    private readonly AdminDbContext _dbContext;
    private readonly ILogger<PermissionService> _logger;

    // 简单的内存缓存（生产环境建议使用 Redis）
    private static readonly ConcurrentDictionary<long, (List<string> Permissions, DateTime ExpireAt)> _permissionCache = new();
    private const int CacheMinutes = 30;

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

    /// <inheritdoc />
    public async Task<List<string>> GetUserPermissionsAsync(long adminUserId)
    {
        // 尝试从缓存获取
        if (_permissionCache.TryGetValue(adminUserId, out var cached) && cached.ExpireAt > DateTime.Now)
        {
            return cached.Permissions;
        }

        // 从数据库获取
        var permissions = await LoadUserPermissionsAsync(adminUserId);

        // 存入缓存
        _permissionCache[adminUserId] = (permissions, DateTime.Now.AddMinutes(CacheMinutes));

        return permissions;
    }

    /// <inheritdoc />
    public async Task<bool> HasPermissionAsync(long adminUserId, string permissionCode)
    {
        var permissions = await GetUserPermissionsAsync(adminUserId);
        
        // 超级管理员拥有所有权限
        if (permissions.Contains("*"))
        {
            return true;
        }

        return permissions.Contains(permissionCode);
    }

    /// <inheritdoc />
    public void InvalidateCache(long adminUserId)
    {
        _permissionCache.TryRemove(adminUserId, out _);
        _logger.LogDebug("用户 {UserId} 权限缓存已失效", adminUserId);
    }

    /// <inheritdoc />
    public async Task<List<PermissionDto>> GetAllPermissionsAsync()
    {
        return await _dbContext.Permissions
            .OrderBy(p => p.Module)
            .ThenBy(p => p.Code)
            .Select(p => new PermissionDto
            {
                Id = p.Id,
                Name = p.Name,
                Code = p.Code,
                Module = p.Module,
                Description = p.Description,
                CreatedAt = p.CreatedAt
            })
            .ToListAsync();
    }

    /// <inheritdoc />
    public async Task<Dictionary<string, List<PermissionDto>>> GetPermissionsByModuleAsync()
    {
        var permissions = await GetAllPermissionsAsync();
        return permissions
            .GroupBy(p => p.Module ?? "其他")
            .ToDictionary(g => g.Key, g => g.ToList());
    }

    /// <inheritdoc />
    public async Task<PermissionDto?> GetByIdAsync(long id)
    {
        var permission = await _dbContext.Permissions.FindAsync(id);
        if (permission == null) return null;

        return new PermissionDto
        {
            Id = permission.Id,
            Name = permission.Name,
            Code = permission.Code,
            Module = permission.Module,
            Description = permission.Description,
            CreatedAt = permission.CreatedAt
        };
    }

    /// <inheritdoc />
    public async Task<PermissionDto> CreateAsync(CreatePermissionRequest request)
    {
        var permission = new Permission
        {
            Name = request.Name,
            Code = request.Code,
            Module = request.Module,
            Description = request.Description,
            CreatedAt = DateTime.Now
        };

        _dbContext.Permissions.Add(permission);
        await _dbContext.SaveChangesAsync();

        _logger.LogInformation("创建权限: {Code}", permission.Code);

        return new PermissionDto
        {
            Id = permission.Id,
            Name = permission.Name,
            Code = permission.Code,
            Module = permission.Module,
            Description = permission.Description,
            CreatedAt = permission.CreatedAt
        };
    }

    /// <inheritdoc />
    public async Task<PermissionDto?> UpdateAsync(long id, UpdatePermissionRequest request)
    {
        var permission = await _dbContext.Permissions.FindAsync(id);
        if (permission == null) return null;

        permission.Name = request.Name;
        permission.Module = request.Module;
        permission.Description = request.Description;

        await _dbContext.SaveChangesAsync();

        _logger.LogInformation("更新权限: {Code}", permission.Code);

        return new PermissionDto
        {
            Id = permission.Id,
            Name = permission.Name,
            Code = permission.Code,
            Module = permission.Module,
            Description = permission.Description,
            CreatedAt = permission.CreatedAt
        };
    }

    /// <inheritdoc />
    public async Task<bool> DeleteAsync(long id)
    {
        var permission = await _dbContext.Permissions.FindAsync(id);
        if (permission == null) return false;

        // 删除关联的角色权限
        var rolePermissions = await _dbContext.RolePermissions
            .Where(rp => rp.PermissionId == id)
            .ToListAsync();
        _dbContext.RolePermissions.RemoveRange(rolePermissions);

        _dbContext.Permissions.Remove(permission);
        await _dbContext.SaveChangesAsync();

        _logger.LogInformation("删除权限: {Code}", permission.Code);

        return true;
    }

    /// <inheritdoc />
    public async Task<bool> CodeExistsAsync(string code, long? excludeId = null)
    {
        var query = _dbContext.Permissions.Where(p => p.Code == code);
        if (excludeId.HasValue)
        {
            query = query.Where(p => p.Id != excludeId.Value);
        }
        return await query.AnyAsync();
    }

    /// <summary>
    /// 从数据库加载用户权限
    /// </summary>
    private async Task<List<string>> LoadUserPermissionsAsync(long adminUserId)
    {
        // 获取用户的所有角色
        var userRoles = await _dbContext.AdminUserRoles
            .Where(ur => ur.AdminUserId == adminUserId)
            .Include(ur => ur.Role)
            .Where(ur => ur.Role.Status == 1)
            .ToListAsync();

        // 检查是否是超级管理员
        if (userRoles.Any(ur => ur.Role.Code == "super_admin"))
        {
            return new List<string> { "*" }; // 超级管理员拥有所有权限
        }

        var roleIds = userRoles.Select(ur => ur.RoleId).ToList();

        // 获取角色关联的权限
        var permissions = await _dbContext.RolePermissions
            .Where(rp => roleIds.Contains(rp.RoleId))
            .Include(rp => rp.Permission)
            .Select(rp => rp.Permission.Code)
            .Distinct()
            .ToListAsync();

        return permissions;
    }
}
