<?php
namespace App;

final class Logger
{
    /** @var string */
    private $path;
    /** @var int */
    private $maxBytes;
    /** @var int */
    private $backups;

    public function __construct($path, $maxBytes = 10485760, $backups = 3)
    {
        $this->path     = $path;
        $this->maxBytes = (int)$maxBytes;
        $this->backups  = (int)$backups;

        $dir = dirname($path);
        if (!is_dir($dir)) {
            // روی هاست‌ها گاهی mkdir خطا می‌دهد؛ بی‌سروصدا بساز اما بعد از آن چک کن
            @mkdir($dir, 0775, true);
        }
        if (!is_dir($dir) || !is_writable($dir)) {
            // اگر پوشه قابل نوشتن نیست، حداقل خطا را در error_log بیانداز
            error_log("[Logger] Log dir not writable: {$dir}");
        }
    }

    public function log($level, $message, array $ctx = [])
    {
        $row = json_encode([
            'ts'   => date('c'),
            'level'=> (string)$level,
            'msg'  => (string)$message,
            'ctx'  => $ctx,
        ], JSON_UNESCAPED_UNICODE);

        $this->rotateIfNeeded(strlen($row) + 1);

        // اگر نوشتن مستقیم شکست خورد، یک fallback بدون LOCK_EX
        $ok = @file_put_contents($this->path, $row . "\n", FILE_APPEND | LOCK_EX);
        if ($ok === false) {
            @file_put_contents($this->path, $row . "\n", FILE_APPEND);
        }
    }

    public function info($m, array $c = []) { $this->log('INFO',  $m, $c); }
    public function warn($m, array $c = []) { $this->log('WARN',  $m, $c); }
    public function error($m, array $c = []){ $this->log('ERROR', $m, $c); }

    private function rotateIfNeeded($incoming)
    {
        $size = 0;
        if (is_file($this->path)) {
            $fs = @filesize($this->path);
            $size = ($fs === false) ? 0 : (int)$fs;
        }
        if ($size + (int)$incoming <= $this->maxBytes) return;

        // شیفت آرشیوها
        for ($i = $this->backups - 1; $i >= 1; $i--) {
            $src = $this->path . '.' . $i;
            $dst = $this->path . '.' . ($i + 1);
            if (is_file($src)) { @rename($src, $dst); }
        }
        // فعلی → .1
        @rename($this->path, $this->path . '.1');
    }
}
