using OmsorgCore.Domain.Entities;

namespace OmsorgCore.Application.Abstractions;

public interface IUserRepository
{
    Task<User?> GetByUsernameAsync(string username, CancellationToken cancellationToken = default);

    /// <summary>Inklusive Role+RolePermissions+PermissionOverrides (für die Rechteauflösung) und Employee (für /api/auth/me). Getrackt - für Mutationsflows (Override hinzufügen/entfernen).</summary>
    Task<User?> GetByIdWithPermissionsAsync(Guid id, CancellationToken cancellationToken = default);

    /// <summary>Wie <see cref="GetByIdWithPermissionsAsync"/>, aber AsNoTracking - für PermissionService's Cache (nie mutiert, wird über Request-Grenzen hinweg gehalten).</summary>
    Task<User?> GetByIdWithPermissionsNoTrackingAsync(Guid id, CancellationToken cancellationToken = default);

    /// <summary>Schlanker Lookup ohne Includes - für den SecurityStamp-Check bei jedem Request.</summary>
    Task<User?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default);

    /// <summary>Inklusive Employee (für die E-Mail-Adresse) und Role (für den Rollennamen in Ergebnissen) - für Admin-Aktionen auf einem bestehenden User.</summary>
    Task<User?> GetByIdWithEmployeeAsync(Guid id, CancellationToken cancellationToken = default);

    Task<IReadOnlyList<User>> GetAllAsync(CancellationToken cancellationToken = default);

    /// <summary>Nur die Ids der User mit dieser Rolle - für die Cache-Invalidierung bei Rollen-Rechte-Änderungen.</summary>
    Task<IReadOnlyList<Guid>> GetUserIdsByRoleAsync(Guid roleId, CancellationToken cancellationToken = default);

    Task<User?> GetByEmployeeIdAsync(Guid employeeId, CancellationToken cancellationToken = default);

    Task<bool> ExistsByUsernameAsync(string username, CancellationToken cancellationToken = default);

    Task AddAsync(User user, CancellationToken cancellationToken = default);

    /// <summary>
    /// Explizit über das DbSet statt über user.PermissionOverrides.Add(...) - sonst behandelt EF Core
    /// die neue Kind-Entität mit bereits client-seitig gesetzter Guid-Id fälschlich als "existiert schon"
    /// und generiert ein UPDATE statt INSERT (0 betroffene Zeilen, DbUpdateConcurrencyException).
    /// </summary>
    Task AddPermissionOverrideAsync(UserPermissionOverride @override, CancellationToken cancellationToken = default);

    Task SaveChangesAsync(CancellationToken cancellationToken = default);
}
