<?php

namespace Alsendo\AlsendoWrapper;

use Alsendo\AlsendoWrapper\Exception\ApiRequestException;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use InvalidArgumentException;

abstract class ApiClient
{
    protected Client $httpClient;
    protected array $config;
    protected array $options = [];
    protected string $platformName;

    /**
     * Initializes a new instance of the class with the provided API URL, configuration, and optional settings.
     *
     * @param string $apiUrl The base URL of the API to interact with.
     * @param array $config An associative array of configuration settings for the client.
     * @param array $options Optional configuration settings that may be used by the client for additional behavior.
     *
     * @return void
     *
     * @throws InvalidArgumentException If the provided apiUrl is not a valid string or is empty.
     * @throws InvalidArgumentException If the config array is not provided or is not an array.
     */
    public function __construct(string $apiUrl, array $config, array $options = [])
    {
        $this->config = $config;
        $this->config['apiUrl'] = $apiUrl;
        $this->httpClient = new Client(
            [
                'base_uri' => $apiUrl
            ]
        );
        $this->options = $options;
    }

    public function setPlatformName(string $platformName): void
    {
        $this->platformName = $platformName;
    }

    private function authorization(): void
    {

    }

    /**
     * Sends an HTTP request to the specified endpoint using the configured HTTP client.
     *
     * @param string $method The HTTP method to use (e.g., 'GET', 'POST', 'PUT', 'DELETE').
     * @param string $endpoint The endpoint path to request, relative to the base URL.
     * @param array $options Additional options to pass to the HTTP request, such as headers, query parameters, or body data.
     *
     * @return string The response body as a string.
     *
     * @throws InvalidArgumentException If the method or endpoint is not provided or invalid.
     * @throws ApiRequestException If an HTTP request fails, preserving the response body for structured error parsing.
     */
    protected function makeRequest(string $method, string $endpoint, array $options = []): string
    {
        $options = array_merge($this->options, $options);
        try {
            $response = $this->httpClient->request($method, $endpoint, $options);
            return $response->getBody()->getContents();
        } catch (RequestException $e) {
            $responseBody = null;
            $statusCode = 0;
            if ($e->hasResponse()) {
                $response = $e->getResponse();
                $statusCode = $response->getStatusCode();
                $responseBody = $response->getBody()->getContents();
            }
            throw new ApiRequestException(
                'Request failed: ' . $e->getMessage(),
                $statusCode,
                $e,
                $responseBody
            );
        }
    }

}
