"""Driven ports for the Identity application layer.

Each is a structural ``Protocol`` implemented by an adapter in ``infrastructure``.
The use cases program against these, never against the concrete library.
"""

from __future__ import annotations

import uuid
from datetime import datetime
from typing import Protocol


class PasswordHasher(Protocol):
    """Argon2id in production (``infrastructure.identity.argon2_hasher``)."""

    def hash(self, plain: str) -> str: ...
    def verify(self, plain: str, hashed: str) -> bool: ...


class TokenIssuer(Protocol):
    """Signs the access token from claims built by the domain."""

    def issue(
        self,
        user_id: uuid.UUID,
        email: str,
        roles: list[str],
        credential_version: int,
    ) -> str: ...


class LoginRateLimiter(Protocol):
    """Per-(email, ip) sliding window; returns False when the request must be denied."""

    def allow(self, email: str, client_ip: str) -> bool: ...


class Clock(Protocol):
    """Injectable time source (keeps use cases deterministic in tests)."""

    def now(self) -> datetime: ...


class AuthAuditSink(Protocol):
    """Append-only audit of authentication outcomes."""

    async def login_succeeded(
        self, *, user_id: uuid.UUID, email: str, roles: list[str]
    ) -> None: ...

    async def login_failed(
        self, *, email: str, user_id: uuid.UUID | None, reason: str | None
    ) -> None: ...
