<?php

declare(strict_types=1);

namespace App\Shared\Infrastructure\Audit\Handler;

use App\Administration\Domain\Event\CompteBloqueTemporairement;
use App\Administration\Domain\Event\ConnexionEchouee;
use App\Administration\Domain\Event\ConnexionReussie;
use App\Administration\Domain\Event\MotDePasseChange;
use App\Shared\Application\Port\AuditLogger;
use Ramsey\Uuid\Uuid;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;

/**
 * Handles authentication events for audit logging.
 *
 * Writes to append-only audit_log table via AuditLogger.
 * All PII (emails, IPs) are hashed before storage.
 *
 * @see Story 1.7 - T4: Listeners Authentification
 * @see AC1: Tracage authentification
 */
final readonly class AuditAuthenticationHandler
{
    public function __construct(
        private AuditLogger $auditLogger,
        private string $appSecret,
    ) {
    }

    /**
     * T4.1: Successful login.
     */
    #[AsMessageHandler(bus: 'event.bus')]
    public function handleConnexionReussie(ConnexionReussie $event): void
    {
        $this->auditLogger->logAuthentication(
            eventType: 'ConnexionReussie',
            userId: Uuid::fromString($event->userId),
            payload: [
                'email_hash' => $this->hashEmail($event->email),
                'result' => 'success',
                'method' => 'password',
            ],
            tenantId: (string) $event->tenantId,
        );
    }

    /**
     * T4.2: Failed login.
     */
    #[AsMessageHandler(bus: 'event.bus')]
    public function handleConnexionEchouee(ConnexionEchouee $event): void
    {
        $this->auditLogger->logAuthentication(
            eventType: 'ConnexionEchouee',
            userId: null, // No user ID for failed logins
            payload: [
                'email_hash' => $this->hashEmail($event->email),
                'result' => 'failure',
                'reason' => $event->reason,
            ],
            tenantId: $event->tenantId !== null ? (string) $event->tenantId : null,
        );
    }

    /**
     * T4.3: Account temporarily locked.
     */
    #[AsMessageHandler(bus: 'event.bus')]
    public function handleCompteBloqueTemporairement(CompteBloqueTemporairement $event): void
    {
        $this->auditLogger->logAuthentication(
            eventType: 'CompteBloqueTemporairement',
            userId: null, // No user ID - we only have email
            payload: [
                'email_hash' => $this->hashEmail($event->email),
                'blocked_for_seconds' => $event->blockedForSeconds,
                'failed_attempts' => $event->failedAttempts,
            ],
            tenantId: $event->tenantId !== null ? (string) $event->tenantId : null,
        );
    }

    /**
     * T4.4: Password changed (via reset or update).
     */
    #[AsMessageHandler(bus: 'event.bus')]
    public function handleMotDePasseChange(MotDePasseChange $event): void
    {
        $this->auditLogger->logAuthentication(
            eventType: 'MotDePasseChange',
            userId: Uuid::fromString($event->userId),
            payload: [
                'email_hash' => $this->hashEmail($event->email),
            ],
            tenantId: (string) $event->tenantId,
        );
    }

    private function hashEmail(string $email): string
    {
        return hash('sha256', strtolower($email) . $this->appSecret);
    }
}
