<?php

/**
 * Class LoggingSoapClient
 *
 * @package Octolize\DhlPolska\API
 */
namespace DhlPolskaVendor\Octolize\DhlPolska\API;

use DhlPolskaVendor\Octolize\DhlPolska\API\Exception\DhlApiException;
use DhlPolskaVendor\Psr\Log\LoggerInterface;
use SoapClient;
/**
 * SoapClient with logging.
 */
class LoggingSoapClient extends SoapClient
{
    private string $api;
    /**
     * @var LoggerInterface
     */
    private LoggerInterface $logger;
    /**
     * LoggingSoapClient constructor.
     *
     * @param string          $api     .
     * @param string|null     $wsdl    .
     * @param array           $options .
     * @param LoggerInterface $logger  .
     *
     * @throws \SoapFault
     */
    public function __construct(string $api, ?string $wsdl, array $options, LoggerInterface $logger)
    {
        parent::__construct($wsdl, $options);
        $this->logger = $logger;
        $this->api = $api;
    }
    /**
     * @param string   $request  .
     * @param string   $location .
     * @param string   $action   .
     * @param int      $version  .
     * @param int $one_way  .
     *
     * @return string|null
     * @throws \Exception
     */
    #[\ReturnTypeWillChange]
    public function __doRequest($request, $location, $action, $version, $one_way = 0)
    {
        $this->logger->debug('DHL ' . $this->api . ' request: ' . $this->mask_password($request));
        $response = $this->do_request($request, $location, $action, $version, $one_way);
        $this->logger->debug('DHL ' . $this->api . ' response: ' . $this->mask_label($response));
        if ($response && strpos($response, '<h1>CException</h1>') !== \false) {
            preg_match('/<p>(.*?)<\/p>/s', $response, $matches);
            $error_msg = isset($matches[1]) ? strip_tags($matches[1]) : $response;
            throw new \Exception(sprintf('DHL WebAPI error: %s', $error_msg));
        }
        return $response;
    }
    /**
     * @param string $request  .
     * @param string $location .
     * @param string $action   .
     * @param int    $version  .
     * @param int    $one_way  .
     *
     * @return string|null
     * @codeCoverageIgnore
     */
    protected function do_request($request, $location, $action, $version, $one_way = 0)
    {
        return parent::__doRequest($request, $location, $action, $version, $one_way);
    }
    /**
     * @param string|null $xml .
     *
     * @return string
     */
    private function mask_label(?string $xml): string
    {
        $xml = (string) preg_replace('/<labelContent>.*?<\/labelContent>/i', '<labelContent>labelContent</labelContent>', (string) $xml);
        return (string) preg_replace('/<labelData>.*?<\/labelData>/i', '<labelData>labelContent</labelData>', $xml);
    }
    /**
     * @param string $xml .
     *
     * @return string
     */
    private function mask_password(string $xml): string
    {
        return (string) preg_replace('/<password>.*?<\/password>/i', '<password>***</password>', $xml);
    }
    /**
     * @param string     $name
     * @param array      $args
     * @param array|null $options
     * @param mixed      $input_headers
     * @param array|null $output_headers
     *
     * @return mixed
     * @throws \JsonException|DhlApiException
     */
    #[\ReturnTypeWillChange]
    public function __soapCall($name, $args, $options = null, $input_headers = null, &$output_headers = null)
    {
        $args = json_decode((string) json_encode($args, \JSON_THROW_ON_ERROR), \true, 512, \JSON_THROW_ON_ERROR);
        try {
            return $this->do_soap_call($name, $args, $options, $input_headers, $output_headers);
        } catch (\SoapFault $exception) {
            $fault_code = (string) $exception->faultcode;
            $code = ctype_digit($fault_code) ? (int) $fault_code : 0;
            throw new DhlApiException($exception->getMessage(), $code, $exception);
        }
    }
    /**
     * @param string     $name
     * @param array      $args
     * @param array|null $options
     * @param mixed      $input_headers
     * @param array|null $output_headers
     *
     * @return mixed
     * @codeCoverageIgnore
     * @throws \SoapFault
     */
    #[\ReturnTypeWillChange]
    protected function do_soap_call($name, $args, $options = null, $input_headers = null, &$output_headers = null)
    {
        return parent::__soapCall($name, $args, $options, $input_headers, $output_headers);
    }
}
