<?php

declare(strict_types=1);

namespace apexl\Io\modules\logger\dto;

use apexl\Io\modules\logger\enums\LogLevel;
use Exception;
use Spatie\DataTransferObject\DataTransferObject;
use Spatie\DataTransferObject\DataTransferObjectCollection;
use stdClass;

class streamConfig extends DataTransferObject
{
    public string $logDirectory;
    public LogLevel $level;
    public DataTransferObjectCollection $handlers;

    public static function fromConfig(array $streamConfig, LogLevel $logLevel, string $logDirectory): streamConfig
    {
        try {
            $streamLevel = static::streamLevel(
                $streamConfig['level'] ?? null,
                $logLevel,
            );

            return new streamConfig([
                'logDirectory' => $logDirectory,
                'level' => $streamLevel,
                'handlers' => new handlerConfigCollection(
                    array_map(fn(array $handler) => new handlerConfig([
                        'destination' => $handler['destination'],
                        'level' => static::handlerLevel($handler['level'] ?? null) ?? $streamLevel,
                        'params' => handlerConfigParams::factory(
                            $handler['destination'],
                            array_filter(
                                (array) $handler,
                                fn(string $key) => !in_array($key, [
                                    'destination',
                                    'level',
                                ]),
                                ARRAY_FILTER_USE_KEY
                            )
                        ),
                    ]), $streamConfig['handlers'])
                ),
            ]);
        } catch (Exception $e) {
            user_error(
                sprintf('Unable to create loggerConfig: %s', $e->getMessage()),
                E_USER_ERROR
            );

            exit;
        }
    }

    private static function streamLevel(?string $streamLevel, LogLevel $globalLevel): LogLevel
    {
        if ($streamLevel) {
            return LogLevel::from($streamLevel);
        }

        return $globalLevel;
    }

    private static function handlerLevel(?string $handlerLevel): ?LogLevel
    {
        return isset($handlerLevel) ? LogLevel::from($handlerLevel) : null;
    }
}
