<?php

declare(strict_types=1);

namespace Gls\GlsPoland\Soap\Client\Caller;

use Gls\GlsPoland\Soap\Client\Exception\SoapException;
use Gls\GlsPoland\Soap\Client\Exception\SoapFault;
use Gls\GlsPoland\Soap\Client\Type\MixedResult;
use Gls\GlsPoland\Soap\Client\Type\MultiArgumentRequestInterface;
use Gls\GlsPoland\Soap\Client\Type\RequestInterface;
use Gls\GlsPoland\Soap\Client\Type\ResultInterface;
use Gls\GlsPoland\Soap\Client\Type\ResultProviderInterface;
use Gls\GlsPoland\Soap\Engine\EngineInterface;

final class EngineCaller implements CallerInterface
{
    /**
     * @var EngineInterface
     */
    private $engine;

    public function __construct(EngineInterface $engine)
    {
        $this->engine = $engine;
    }

    public function call(string $method, RequestInterface $request): ResultInterface
    {
        try {
            $arguments = $request instanceof MultiArgumentRequestInterface
                ? $request->getArguments()
                : [$request];
            $result = $this->engine->request($method, $arguments);

            if ($result instanceof ResultProviderInterface) {
                $result = $result->getResult();
            }

            if (!$result instanceof ResultInterface) {
                $result = new MixedResult($result);
            }

            return $result;
        } catch (\SoapFault $fault) {
            throw SoapFault::fromNative($fault);
        } catch (\Exception $exception) {
            throw SoapException::fromThrowable($exception);
        }
    }
}
