using TakeoutSaaS.Domain.Identity.Entities;
using TakeoutSaaS.Domain.Identity.Enums;

namespace TakeoutSaaS.Domain.Identity.Repositories;

/// <summary>
/// 后台用户仓储契约。
/// </summary>
public interface IIdentityUserRepository
{
    /// <summary>
    /// 根据租户与账号获取后台用户。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="account">账号。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>后台用户或 null。</returns>
    Task<IdentityUser?> FindByAccountAsync(long tenantId, string account, CancellationToken cancellationToken = default);

    /// <summary>
    /// 判断账号是否存在。
    /// </summary>
    /// <param name="account">账号。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>存在返回 true。</returns>
    Task<bool> ExistsByAccountAsync(string account, CancellationToken cancellationToken = default);

    /// <summary>
    /// 判断账号是否存在（租户内，可排除指定用户）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="account">账号。</param>
    /// <param name="excludeUserId">排除的用户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>存在返回 true。</returns>
    Task<bool> ExistsByAccountAsync(
        long tenantId,
        string account,
        long? excludeUserId = null,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 判断手机号是否存在（租户内，可排除指定用户）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="phone">手机号。</param>
    /// <param name="excludeUserId">排除的用户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>存在返回 true。</returns>
    Task<bool> ExistsByPhoneAsync(
        long tenantId,
        string phone,
        long? excludeUserId = null,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 判断邮箱是否存在（租户内，可排除指定用户）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="email">邮箱。</param>
    /// <param name="excludeUserId">排除的用户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>存在返回 true。</returns>
    Task<bool> ExistsByEmailAsync(
        long tenantId,
        string email,
        long? excludeUserId = null,
        CancellationToken cancellationToken = default);

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

    /// <summary>
    /// 根据 ID 获取后台用户（用于更新，返回可跟踪实体）。
    /// </summary>
    /// <param name="userId">用户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>后台用户或 null。</returns>
    Task<IdentityUser?> GetForUpdateAsync(long userId, CancellationToken cancellationToken = default);

    /// <summary>
    /// 根据 ID 获取后台用户（用于更新，包含已删除数据）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="userId">用户 ID。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>后台用户或 null。</returns>
    Task<IdentityUser?> GetForUpdateIncludingDeletedAsync(
        long tenantId,
        long userId,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 按租户与关键字查询后台用户列表（仅读）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="keyword">可选关键字（账号/名称）。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>后台用户列表。</returns>
    Task<IReadOnlyList<IdentityUser>> SearchAsync(long tenantId, string? keyword, CancellationToken cancellationToken = default);

    /// <summary>
    /// 分页查询后台用户列表。
    /// </summary>
    /// <param name="filter">查询过滤条件。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>分页结果。</returns>
    Task<(IReadOnlyList<IdentityUser> Items, int Total)> SearchPagedAsync(
        IdentityUserSearchFilter filter,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取指定租户、用户集合对应的用户（只读）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="userIds">用户 ID 集合。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>后台用户列表。</returns>
    Task<IReadOnlyList<IdentityUser>> GetByIdsAsync(long tenantId, IEnumerable<long> userIds, CancellationToken cancellationToken = default);

    /// <summary>
    /// 批量获取后台用户（可用于更新，支持包含已删除数据）。
    /// </summary>
    /// <param name="tenantId">租户 ID。</param>
    /// <param name="userIds">用户 ID 集合。</param>
    /// <param name="includeDeleted">是否包含已删除数据。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>后台用户列表。</returns>
    Task<IReadOnlyList<IdentityUser>> GetForUpdateByIdsAsync(
        long tenantId,
        IEnumerable<long> userIds,
        bool includeDeleted,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// 新增后台用户。
    /// </summary>
    /// <param name="user">后台用户实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步操作任务。</returns>
    Task AddAsync(IdentityUser user, CancellationToken cancellationToken = default);

    /// <summary>
    /// 删除后台用户（软删除）。
    /// </summary>
    /// <param name="user">后台用户实体。</param>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步操作任务。</returns>
    Task RemoveAsync(IdentityUser user, CancellationToken cancellationToken = default);

    /// <summary>
    /// 持久化仓储变更。
    /// </summary>
    /// <param name="cancellationToken">取消标记。</param>
    /// <returns>异步操作任务。</returns>
    Task SaveChangesAsync(CancellationToken cancellationToken = default);
}

/// <summary>
/// 后台用户查询过滤条件。
/// </summary>
public sealed record IdentityUserSearchFilter
{
    /// <summary>
    /// 租户 ID。
    /// </summary>
    public long? TenantId { get; init; }

    /// <summary>
    /// 关键字（账号/姓名/手机号/邮箱）。
    /// </summary>
    public string? Keyword { get; init; }

    /// <summary>
    /// 用户状态。
    /// </summary>
    public IdentityUserStatus? Status { get; init; }

    /// <summary>
    /// 角色 ID。
    /// </summary>
    public long? RoleId { get; init; }

    /// <summary>
    /// 创建开始时间（UTC）。
    /// </summary>
    public DateTime? CreatedAtFrom { get; init; }

    /// <summary>
    /// 创建结束时间（UTC）。
    /// </summary>
    public DateTime? CreatedAtTo { get; init; }

    /// <summary>
    /// 最近登录开始时间（UTC）。
    /// </summary>
    public DateTime? LastLoginFrom { get; init; }

    /// <summary>
    /// 最近登录结束时间（UTC）。
    /// </summary>
    public DateTime? LastLoginTo { get; init; }

    /// <summary>
    /// 是否包含已删除数据。
    /// </summary>
    public bool IncludeDeleted { get; init; }

    /// <summary>
    /// 页码（从 1 开始）。
    /// </summary>
    public int Page { get; init; } = 1;

    /// <summary>
    /// 每页条数。
    /// </summary>
    public int PageSize { get; init; } = 20;

    /// <summary>
    /// 排序字段。
    /// </summary>
    public string? SortBy { get; init; }

    /// <summary>
    /// 是否降序。
    /// </summary>
    public bool SortDescending { get; init; } = true;
}
