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

namespace TakeoutSaaS.Infrastructure.Identity.Persistence;

/// <summary>
/// EF Core 后台用户仓储实现。
/// </summary>
public sealed class EfIdentityUserRepository(IdentityDbContext dbContext) : IIdentityUserRepository
{
    /// <summary>
    /// 根据账号获取后台用户。
    /// </summary>
    /// <param name="account">账号。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>后台用户或 null。</returns>
    public Task<IdentityUser?> FindByAccountAsync(string account, CancellationToken cancellationToken = default)
        => dbContext.IdentityUsers.AsNoTracking().FirstOrDefaultAsync(x => x.Account == account, cancellationToken);

    /// <summary>
    /// 判断账号是否存在。
    /// </summary>
    /// <param name="account">账号。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>存在返回 true。</returns>
    public Task<bool> ExistsByAccountAsync(string account, CancellationToken cancellationToken = default)
    {
        // 1. 标准化账号
        var normalized = account.Trim();
        // 2. 查询是否存在
        return dbContext.IdentityUsers.AnyAsync(x => x.Account == normalized, cancellationToken);
    }

    /// <summary>
    /// 根据 ID 获取后台用户。
    /// </summary>
    /// <param name="userId">用户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>后台用户或 null。</returns>
    public Task<IdentityUser?> FindByIdAsync(long userId, CancellationToken cancellationToken = default)
        => dbContext.IdentityUsers.AsNoTracking().FirstOrDefaultAsync(x => x.Id == userId, cancellationToken);

    /// <summary>
    /// 按租户与关键字搜索后台用户（只读）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="keyword">关键字（账号/名称）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>后台用户列表。</returns>
    public async Task<IReadOnlyList<IdentityUser>> SearchAsync(long tenantId, string? keyword, CancellationToken cancellationToken = default)
    {
        // 1. 构建基础查询
        var query = dbContext.IdentityUsers
            .AsNoTracking()
            .Where(x => x.TenantId == tenantId);

        // 2. 关键字过滤
        if (!string.IsNullOrWhiteSpace(keyword))
        {
            var normalized = keyword.Trim();
            query = query.Where(x => x.Account.Contains(normalized) || x.DisplayName.Contains(normalized));
        }

        // 3. 返回列表
        return await query.ToListAsync(cancellationToken);
    }

    /// <summary>
    /// 根据 ID 集合批量获取后台用户（只读）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="userIds">用户 ID 集合。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>后台用户列表。</returns>
    public Task<IReadOnlyList<IdentityUser>> GetByIdsAsync(long tenantId, IEnumerable<long> userIds, CancellationToken cancellationToken = default)
        => dbContext.IdentityUsers.AsNoTracking()
            .Where(x => x.TenantId == tenantId && userIds.Contains(x.Id))
            .ToListAsync(cancellationToken)
            .ContinueWith(t => (IReadOnlyList<IdentityUser>)t.Result, cancellationToken);

    /// <summary>
    /// 新增后台用户。
    /// </summary>
    /// <param name="user">后台用户实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步任务。</returns>
    public Task AddAsync(IdentityUser user, CancellationToken cancellationToken = default)
    {
        // 1. 添加实体
        dbContext.IdentityUsers.Add(user);
        // 2. 返回完成任务
        return Task.CompletedTask;
    }

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