<?php
declare(strict_types=1);

namespace App\Core\Logging;

final class FileLogger
{
    public function __construct(
        private readonly string $directory,
        private readonly string $filename = 'axiom.log',
        private readonly int $maxBytes = 5242880,
        private readonly int $retention = 5,
    ) {
    }

    /** @param array<string,mixed> $context */
    public function log(string $level, string $message, array $context = []): void
    {
        $this->ensureDirectory();
        $this->rotateIfNeeded();

        $record = [
            'timestamp' => (new \DateTimeImmutable())->format(DATE_ATOM),
            'level' => strtoupper($level),
            'message' => $message,
            'context' => $context,
        ];

        $line = json_encode($record, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        if ($line === false) {
            $line = '{"level":"ERROR","message":"Unable to encode log record"}';
        }

        file_put_contents($this->path(), $line . PHP_EOL, FILE_APPEND | LOCK_EX);
    }

    /** @param array<string,mixed> $context */
    public function info(string $message, array $context = []): void { $this->log('INFO', $message, $context); }
    /** @param array<string,mixed> $context */
    public function warning(string $message, array $context = []): void { $this->log('WARNING', $message, $context); }
    /** @param array<string,mixed> $context */
    public function error(string $message, array $context = []): void { $this->log('ERROR', $message, $context); }
    /** @param array<string,mixed> $context */
    public function security(string $message, array $context = []): void { $this->log('SECURITY', $message, $context); }

    public function path(): string
    {
        return rtrim($this->directory, '/\\') . DIRECTORY_SEPARATOR . $this->filename;
    }

    private function ensureDirectory(): void
    {
        if (!is_dir($this->directory) && !mkdir($this->directory, 0775, true) && !is_dir($this->directory)) {
            throw new \RuntimeException('Impossible de créer le répertoire de logs AXIOM.');
        }
    }

    private function rotateIfNeeded(): void
    {
        $path = $this->path();
        if (!is_file($path) || filesize($path) < $this->maxBytes) {
            return;
        }

        for ($i = $this->retention - 1; $i >= 1; $i--) {
            $source = $path . '.' . $i;
            if (is_file($source)) {
                rename($source, $path . '.' . ($i + 1));
            }
        }
        rename($path, $path . '.1');
    }
}
