<?php

/**
 * Фасад для роботи з логуванням
 *
 * @package Flowaxy\Support\Facades
 */

declare(strict_types=1);

namespace Flowaxy\Support\Facades;

use Flowaxy\Core\Contracts\LoggerInterface;
use Flowaxy\Infrastructure\Logging\Logger;
use Flowaxy\Core\System\PathResolver;

use RuntimeException;
use Throwable;

use function interface_exists;
use function class_exists;
use function file_exists;
use function is_readable;
use function spl_autoload_functions;
use function spl_autoload_call;

// Класи завантажуються через autoloader

final class Log extends Facade
{
    protected static function getFacadeAccessor(): string
    {
        return LoggerInterface::class;
    }

    /**
     * Отримання екземпляра Logger
     */
    public static function instance(): LoggerInterface
    {
        // Класи завантажуються через autoloader

        try {
            $container = static::getContainer();
            if ($container && $container->has(LoggerInterface::class)) {
                return $container->make(LoggerInterface::class);
            }
        } catch (RuntimeException $e) {
            // Контейнер еще не инициализирован, используем fallback
        }

        // Fallback на getInstance
        if (class_exists(Logger::class)) {
            return Logger::getInstance();
        }

        // Если Logger все еще не загружен, пробуем через autoloader
        if (spl_autoload_functions()) {
            // Пробуем загрузить класс через autoloader
            if (!class_exists(Logger::class, false)) {
                // Пытаемся вызвать autoloader
                spl_autoload_call(Logger::class);
            }
            if (class_exists(Logger::class)) {
                return Logger::getInstance();
            }
        }

        // Если Logger все еще не загружен, создаем простой fallback - молча игнорируем
        // Вместо исключения возвращаем заглушку, которая ничего не делает
        return new class implements LoggerInterface {
            public function log(int $level, string $message, array $context = []): void {}
            public function logError(string $message, array $context = []): void {}
            public function logWarning(string $message, array $context = []): void {}
            public function logInfo(string $message, array $context = []): void {}
            public function logDebug(string $message, array $context = []): void {}
            public function logCritical(string $message, array $context = []): void {}
            public function logException(Throwable $exception, array $context = []): void {}
            public function getRecentLogs(int $lines = 100): array { return []; }
            public function clearLogs(): bool { return false; }
            public function getStats(): array { return []; }
            public function reloadSettings(): void {}
            public function getSetting(string $key, string $default = ''): string { return $default; }
            public function setSetting(string $key, string $value): void {}
        };
    }

    /**
     * Логування повідомлення
     *
     * @param int $level
     * @param string $message
     * @param array<string, mixed> $context
     * @return void
     */
    public static function log(int $level, string $message, array $context = []): void
    {
        static::instance()->log($level, $message, $context);
    }

    /**
     * Логування помилки
     *
     * @param string $message
     * @param array<string, mixed> $context
     * @return void
     */
    public static function Error(string $message, array $context = []): void
    {
        static::instance()->logError($message, $context);
    }

    /**
     * Логування попередження
     *
     * @param string $message
     * @param array<string, mixed> $context
     * @return void
     */
    public static function Warning(string $message, array $context = []): void
    {
        static::instance()->logWarning($message, $context);
    }

    /**
     * Логування інформації
     */
    public static function Info(string $message, array $context = []): void
    {
        static::instance()->logInfo($message, $context);
    }

    /**
     * Логування відлагодження
     */
    public static function Debug(string $message, array $context = []): void
    {
        static::instance()->logDebug($message, $context);
    }

    /**
     * Логування критичної помилки
     */
    public static function Critical(string $message, array $context = []): void
    {
        static::instance()->logCritical($message, $context);
    }

    /**
     * Логування винятку
     */
    public static function exception(\Throwable $exception): void
    {
        static::instance()->logException($exception);
    }

    /**
     * Обработка вызовов с маленькой буквы (перенаправление на методы с большой буквы)
     *
     * @param string $method
     * @param array<int, mixed> $args
     * @return mixed
     */
    public static function __callStatic(string $method, array $args): mixed
    {
        // Маппинг методов с маленькой буквы на методы с большой буквы
        $methodMap = [
            'warning' => 'Warning',
            'error' => 'Error',
            'info' => 'Info',
            'debug' => 'Debug',
            'critical' => 'Critical',
        ];

        // Если метод найден в маппинге, вызываем метод с большой буквы
        if (isset($methodMap[$method])) {
            $upperMethod = $methodMap[$method];
            if (method_exists(static::class, $upperMethod)) {
                return static::$upperMethod(...$args);
            }
        }

        // Если метод не найден, пробуем вызвать через родительский __callStatic
        return parent::__callStatic($method, $args);
    }
}
