<?php

namespace apexl\Io\services;

use apexl\Io\includes\HookManager;
use apexl\Io\interfaces\OutputManagerInterface;
use Psr\Http\Message\ServerRequestInterface;

/**
 * Class Messages
 * Class to provide a generalised store for communication - allows the addition to, and subtraction from the api response.
 * @package apexl\Io\includes
 */
final class SimpleOutputManager implements OutputManagerInterface
{
    public function __construct(
        private readonly HttpPaths $httpPaths,
        private readonly HookManager $hookManager,
        private array $response = [],
        private array $messages = [],
        private array $metadata = [],
    ) {}

    public function addMessage(
        string $name,
        string $type,
        string $content,
        string $icon = '',
        ?int $timeout = null,
        ?string $id = null
    ): void {
        $message = [
            'content' => $content,
            'type' => $type,
            'id' => $id ?? uniqid(),
            'icon' => $icon,
            'timeout' => $timeout,
        ];
        $message = $this->hookManager->processHook(self::HOOK__ADD_MESSAGE, $message, $name, $this);
        $this->messages[$name] = $message;
    }

    public function addRedirect(string $name, string $destination): void
    {
        $this->addMetadata($name, 'redirect', $destination);
    }

    public function addMetadata(string $name, string $type, mixed $contents): void
    {
        $metadata = [$type => $contents];
        $metadata = $this->hookManager->processHook(self::HOOK__ADD_METADATA, $metadata, $name, $this);

        $this->metadata[$name] = $metadata;
    }

    public function addResponse(?ServerRequestInterface $request = null, array $response = [], bool $success = true): void
    {
        //Allows us to alter the response provided with a hook. We require the request to grab the current route.
        //allow us to inject data to the response object from elseware and maintain it (or override as appropriate)
        $response = [
            ...$this->response,
            ...$response,
            'success' => $success
        ];

        $this->response = $this->hookManager->processHook(
            self::HOOK__ADD_RESPONSE,
            $response,
            $request ? $this->httpPaths->getRouteName($request) : null,
        );
    }

    public function getOutput(): array
    {
        $output = [];

        if ($this->response) {
            $output = [
                ...$output,
                ...$this->response,
            ];
        }

        foreach ($this->metadata as $metadata) {
            $output = [
                ...$output,
                ...$metadata,
            ];
        }

        if ($this->messages) {
            $output['messages'] = $this->messages;
        }

        return $output;
    }

    public function getMetadata(string $name): mixed
    {
        return $this->metadata[$name] ?? null;
    }
}
