<?php

declare(strict_types=1);

namespace App\Application\Security\ValueObjects;

use DateTimeImmutable;
use DateTimeInterface;

final class OWASPLogFormat
{
    public function __construct(
        private DateTimeImmutable $datetime,
        private string $appid,
        private string $event,
        private string $level,
        private string $description,
        private ?string $useragent = null,
        private ?string $sourceIp = null,
        private ?string $hostIp = null,
        private ?string $hostname = null,
        private ?string $protocol = null,
        private ?string $port = null,
        private ?string $requestUri = null,
        private ?string $requestMethod = null,
        private ?string $region = null,
        private ?string $geo = null
    ) {
    }

    public static function create(
        string $appid,
        string $event,
        string $level,
        string $description,
        SecurityContext $context,
        RequestContext $requestContext
    ): self {
        return new self(
            new DateTimeImmutable(),
            $appid,
            $event,
            $level,
            $description,
            $context->getUserAgent(),
            $context->getSourceIp(),
            $requestContext->getHostIp(),
            $requestContext->getHostname(),
            $requestContext->getProtocol(),
            $requestContext->getPort(),
            $requestContext->getRequestUri(),
            $requestContext->getRequestMethod(),
            $requestContext->getRegion(),
            $requestContext->getGeo()
        );
    }

    public function toArray(): array
    {
        $data = [
            'datetime' => $this->datetime->format(DateTimeInterface::ATOM),
            'appid' => $this->appid,
            'event' => $this->event,
            'level' => $this->level,
            'description' => $this->description,
        ];

        // Nur nicht-null Werte hinzufügen
        if ($this->useragent !== null) {
            $data['useragent'] = $this->useragent;
        }
        if ($this->sourceIp !== null) {
            $data['source_ip'] = $this->sourceIp;
        }
        if ($this->hostIp !== null) {
            $data['host_ip'] = $this->hostIp;
        }
        if ($this->hostname !== null) {
            $data['hostname'] = $this->hostname;
        }
        if ($this->protocol !== null) {
            $data['protocol'] = $this->protocol;
        }
        if ($this->port !== null) {
            $data['port'] = $this->port;
        }
        if ($this->requestUri !== null) {
            $data['request_uri'] = $this->requestUri;
        }
        if ($this->requestMethod !== null) {
            $data['request_method'] = $this->requestMethod;
        }
        if ($this->region !== null) {
            $data['region'] = $this->region;
        }
        if ($this->geo !== null) {
            $data['geo'] = $this->geo;
        }

        return $data;
    }

    public function toJson(): string
    {
        return json_encode($this->toArray(), JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES);
    }

    public function getDescription(): string
    {
        return $this->description;
    }
}
