<?php
declare(strict_types=1);

namespace App\Framework\Api;

use App\Framework\Http\Method;
use App\Framework\HttpClient\ClientOptions;
use App\Framework\HttpClient\ClientRequest;
use App\Framework\HttpClient\ClientResponse;
use App\Framework\HttpClient\CurlHttpClient;
use App\Framework\HttpClient\HttpClient;

trait ApiRequestTrait
{
    private string $baseUrl;
    private ClientOptions $defaultOptions;
    private HttpClient $httpClient;

    /**
     * Sendet eine Anfrage an die API
     */
    public function sendRequest(
        Method         $method,
        string         $endpoint,
        array          $data = [],
        ?ClientOptions $options = null
    ): ClientResponse {
        $url = $this->baseUrl . '/' . ltrim($endpoint, '/');
        $options = $options ?? $this->defaultOptions;

        $request = ClientRequest::json(
            method: $method,
            url: $url,
            data: $data,
            options: $options
        );

        $response = $this->httpClient->send($request);

        $this->handleResponseErrors($response);

        return $response;
    }

    /**
     * Verarbeitet Fehler in der API-Antwort
     */
    private function handleResponseErrors(ClientResponse $response): void
    {
        if ($response->status->value < 400) {
            return;
        }

        $responseData = json_decode($response->body, true) ?: [];

        throw new ApiException(
            $this->formatErrorMessage($responseData),
            $response->status->value,
            $response
        );
    }

    /**
     * Formatiert eine benutzerfreundliche Fehlermeldung
     */
    private function formatErrorMessage(array $responseData): string
    {
        $errorMessage = 'API-Fehler';

        if (isset($responseData['detail'])) {
            $errorMessage .= ': ' . $responseData['detail'];

            if (isset($responseData['validation_messages'])) {
                $errorMessage .= ' - Validierungsfehler: ' . json_encode(
                    $responseData['validation_messages'],
                    JSON_UNESCAPED_UNICODE
                );
            }
        } elseif (isset($responseData['error'])) {
            $errorMessage .= ': ' . $responseData['error'];
        }

        return $errorMessage;
    }

    /**
     * Dekodiert den Response-Body als JSON
     */
    protected function decodeJson(ClientResponse $response): array
    {
        return json_decode($response->body, true) ?: [];
    }
}
