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 EfMiniUserRepository(IdentityDbContext dbContext) : IMiniUserRepository
{
    /// <summary>
    /// 根据 OpenId 获取小程序用户。
    /// </summary>
    /// <param name="openId">微信 OpenId。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>匹配的小程序用户或 null。</returns>
    public Task<MiniUser?> FindByOpenIdAsync(string openId, CancellationToken cancellationToken = default)
        => dbContext.MiniUsers.AsNoTracking().FirstOrDefaultAsync(x => x.OpenId == openId, cancellationToken);

    /// <summary>
    /// 根据用户 ID 获取小程序用户。
    /// </summary>
    /// <param name="id">用户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>匹配的小程序用户或 null。</returns>
    public Task<MiniUser?> FindByIdAsync(long id, CancellationToken cancellationToken = default)
        => dbContext.MiniUsers.AsNoTracking().FirstOrDefaultAsync(x => x.Id == id, cancellationToken);

    /// <inheritdoc />
    public async Task<IReadOnlyList<MiniUser>> GetByIdsAsync(
        IReadOnlyCollection<long> ids,
        long tenantId,
        CancellationToken cancellationToken = default)
    {
        if (ids.Count == 0)
        {
            return [];
        }

        return await dbContext.MiniUsers
            .AsNoTracking()
            .Where(x => x.TenantId == tenantId && ids.Contains(x.Id))
            .ToListAsync(cancellationToken);
    }

    /// <summary>
    /// 创建或更新小程序用户信息。
    /// </summary>
    /// <param name="openId">微信 OpenId。</param>
    /// <param name="unionId">微信 UnionId。</param>
    /// <param name="nickname">昵称。</param>
    /// <param name="avatar">头像地址。</param>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>创建或更新后的小程序用户。</returns>
    public async Task<MiniUser> CreateOrUpdateAsync(string openId, string? unionId, string? nickname, string? avatar, long tenantId, CancellationToken cancellationToken = default)
    {
        // 1. 查询现有用户
        var user = await dbContext.MiniUsers.FirstOrDefaultAsync(x => x.OpenId == openId, cancellationToken);
        if (user == null)
        {
            // 2. 未找到则创建
            user = new MiniUser
            {
                Id = 0,
                OpenId = openId,
                UnionId = unionId,
                Nickname = nickname ?? "小程序用户",
                Avatar = avatar,
                TenantId = tenantId
            };
            dbContext.MiniUsers.Add(user);
        }
        else
        {
            // 3. 已存在则更新可变字段
            user.UnionId = unionId ?? user.UnionId;
            user.Nickname = nickname ?? user.Nickname;
            user.Avatar = avatar ?? user.Avatar;
        }

        // 4. 保存更改
        await dbContext.SaveChangesAsync(cancellationToken);
        return user;
    }
}
