using Microsoft.AspNetCore.Identity;
using ROLAC.API.DTOs.Auth;
using ROLAC.API.Entities;

namespace ROLAC.API.Services;

public interface IAuthService
{
    /// <summary>
    /// Validates credentials and returns a new access token plus the raw refresh token
    /// that must be stored in an HttpOnly cookie by the caller.
    /// Throws <see cref="UnauthorizedAccessException"/> on any auth failure.
    /// </summary>
    Task<(LoginResponse Response, string RawRefreshToken)> LoginAsync(
        LoginRequest request,
        string? ipAddress  = null,
        string? deviceInfo = null);

    /// <summary>
    /// Validates a raw refresh token, revokes it, and issues a new token pair (rotation).
    /// Throws <see cref="UnauthorizedAccessException"/> if the token is not found,
    /// expired, or already revoked.
    /// </summary>
    Task<(LoginResponse Response, string RawRefreshToken)> RefreshAsync(
        string rawRefreshToken,
        string? ipAddress = null);

    /// <summary>
    /// Issues a fresh access token + refresh token for an already-verified user (no password
    /// check). Stores the refresh token and returns the raw value for the caller to put in the
    /// HttpOnly cookie. Used by passwordless flows such as accepting an invitation link.
    /// </summary>
    Task<(LoginResponse Response, string RawRefreshToken)> IssueSessionAsync(
        AppUser user,
        string? ipAddress  = null,
        string? deviceInfo = null);

    /// <summary>
    /// Revokes the refresh token identified by its raw value.
    /// Silently succeeds if the token is not found.
    /// </summary>
    Task LogoutAsync(string rawRefreshToken);

    /// <summary>
    /// Changes the password for an already-authenticated user. Verifies the current
    /// password and enforces the configured Identity password policy via
    /// <c>UserManager.ChangePasswordAsync</c>. On success, revokes the user's other
    /// active refresh tokens (keeping the one matching <paramref name="currentRawRefreshToken"/>)
    /// and writes a security audit entry. Returns the <see cref="IdentityResult"/> so the
    /// caller can surface failures; never throws on a bad password.
    /// </summary>
    Task<IdentityResult> ChangePasswordAsync(
        string  userId,
        string  currentPassword,
        string  newPassword,
        string? currentRawRefreshToken);

    /// <summary>
    /// Builds the UserInfo payload (identity, roles, and effective permissions) for an
    /// already-authenticated user. Used by GET /api/auth/me to refresh permissions
    /// after an admin edits the matrix, without forcing a re-login.
    /// </summary>
    Task<UserInfo> BuildUserInfoAsync(AppUser user, IList<string> roles);
}
