using Microsoft.EntityFrameworkCore;
using TakeoutSaaS.Domain.Identity.Entities;
using TakeoutSaaS.Domain.Identity.Repositories;

namespace TakeoutSaaS.Infrastructure.Identity.Persistence;

/// <summary>
/// EF 权限仓储。
/// </summary>
public sealed class EfPermissionRepository(IdentityDbContext dbContext) : IPermissionRepository
{
    /// <summary>
    /// 根据权限 ID 获取权限。
    /// </summary>
    /// <param name="permissionId">权限 ID。</param>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>权限实体或 null。</returns>
    public Task<Permission?> FindByIdAsync(long permissionId, long tenantId, CancellationToken cancellationToken = default)
        => dbContext.Permissions.AsNoTracking().FirstOrDefaultAsync(x => x.Id == permissionId && x.TenantId == tenantId, cancellationToken);

    /// <summary>
    /// 根据权限编码获取权限。
    /// </summary>
    /// <param name="code">权限编码。</param>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>权限实体或 null。</returns>
    public Task<Permission?> FindByCodeAsync(string code, long tenantId, CancellationToken cancellationToken = default)
        => dbContext.Permissions.AsNoTracking().FirstOrDefaultAsync(x => x.Code == code && x.TenantId == tenantId, cancellationToken);

    /// <summary>
    /// 根据权限编码集合批量获取权限。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="codes">权限编码集合。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>权限列表。</returns>
    public Task<IReadOnlyList<Permission>> GetByCodesAsync(long tenantId, IEnumerable<string> codes, CancellationToken cancellationToken = default)
    {
        // 1. 规范化编码集合
        var normalizedCodes = codes
            .Where(code => !string.IsNullOrWhiteSpace(code))
            .Select(code => code.Trim())
            .Distinct()
            .ToArray();

        // 2. 按租户筛选权限
        return dbContext.Permissions.AsNoTracking()
            .Where(x => x.TenantId == tenantId && normalizedCodes.Contains(x.Code))
            .ToListAsync(cancellationToken)
            .ContinueWith(t => (IReadOnlyList<Permission>)t.Result, cancellationToken);
    }

    /// <summary>
    /// 根据权限 ID 集合批量获取权限。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="permissionIds">权限 ID 集合。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>权限列表。</returns>
    public Task<IReadOnlyList<Permission>> GetByIdsAsync(long tenantId, IEnumerable<long> permissionIds, CancellationToken cancellationToken = default)
        => dbContext.Permissions.AsNoTracking()
            .Where(x => x.TenantId == tenantId && permissionIds.Contains(x.Id))
            .ToListAsync(cancellationToken)
            .ContinueWith(t => (IReadOnlyList<Permission>)t.Result, cancellationToken);

    /// <summary>
    /// 按关键字搜索权限。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="keyword">搜索关键字。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>权限列表。</returns>
    public Task<IReadOnlyList<Permission>> SearchAsync(long tenantId, string? keyword, CancellationToken cancellationToken = default)
    {
        // 1. 构建基础查询
        var query = dbContext.Permissions.AsNoTracking().Where(x => x.TenantId == tenantId);
        if (!string.IsNullOrWhiteSpace(keyword))
        {
            // 2. 追加关键字过滤
            var normalized = keyword.Trim();
            query = query.Where(x => x.Name.Contains(normalized) || x.Code.Contains(normalized));
        }

        // 3. 返回列表
        return query.ToListAsync(cancellationToken)
            .ContinueWith(t => (IReadOnlyList<Permission>)t.Result, cancellationToken);
    }

    /// <summary>
    /// 新增权限。
    /// </summary>
    /// <param name="permission">权限实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    public Task AddAsync(Permission permission, CancellationToken cancellationToken = default)
    {
        // 1. 添加实体
        dbContext.Permissions.Add(permission);
        // 2. 返回完成任务
        return Task.CompletedTask;
    }

    /// <summary>
    /// 更新权限。
    /// </summary>
    /// <param name="permission">权限实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    public Task UpdateAsync(Permission permission, CancellationToken cancellationToken = default)
    {
        // 1. 标记实体更新
        dbContext.Permissions.Update(permission);
        // 2. 返回完成任务
        return Task.CompletedTask;
    }

    /// <summary>
    /// 删除指定权限。
    /// </summary>
    /// <param name="permissionId">权限 ID。</param>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    public async Task DeleteAsync(long permissionId, long tenantId, CancellationToken cancellationToken = default)
    {
        // 1. 查询目标权限
        var entity = await dbContext.Permissions.FirstOrDefaultAsync(x => x.Id == permissionId && x.TenantId == tenantId, cancellationToken);
        if (entity != null)
        {
            // 2. 删除实体
            dbContext.Permissions.Remove(entity);
        }
    }

    /// <summary>
    /// 保存仓储变更。
    /// </summary>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>保存任务。</returns>
    public Task SaveChangesAsync(CancellationToken cancellationToken = default)
        => dbContext.SaveChangesAsync(cancellationToken);
}
