<?php
declare(strict_types=1);

namespace App\Core\Audit;

use App\Core\Database;
use App\Core\Logging\FileLogger;
use PDO;

final class AuditLogger
{
    public function __construct(private readonly ?FileLogger $fallbackLogger = null)
    {
    }

    /** @param array<string,mixed>|null $before @param array<string,mixed>|null $after */
    public function record(string $action, string $module, ?string $entityType = null, int|string|null $entityId = null, ?array $before = null, ?array $after = null): void
    {
        try {
            $pdo = Database::connection();
            $stmt = $pdo->prepare(
                'INSERT INTO axiom_audit_logs
                (user_id, action, module, entity_type, entity_id, before_json, after_json, ip_address, user_agent, created_at)
                VALUES (:user_id, :action, :module, :entity_type, :entity_id, :before_json, :after_json, :ip_address, :user_agent, NOW())'
            );
            $stmt->execute([
                'user_id' => $_SESSION['user']['id'] ?? $_SESSION['user_id'] ?? null,
                'action' => $action,
                'module' => $module,
                'entity_type' => $entityType,
                'entity_id' => $entityId === null ? null : (string)$entityId,
                'before_json' => $before === null ? null : json_encode($before, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
                'after_json' => $after === null ? null : json_encode($after, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
                'ip_address' => $_SERVER['REMOTE_ADDR'] ?? null,
                'user_agent' => substr((string)($_SERVER['HTTP_USER_AGENT'] ?? ''), 0, 500),
            ]);
        } catch (\Throwable $exception) {
            $this->fallbackLogger?->warning('audit.database_unavailable', [
                'action' => $action,
                'module' => $module,
                'error' => $exception->getMessage(),
            ]);
        }
    }
}
