<?php

declare(strict_types=1);

namespace App\Framework\HttpClient;

use App\Framework\Http\HeaderManipulator;
use App\Framework\Http\Headers;
use App\Framework\Http\Status;
use App\Framework\HttpClient\Curl\Handle;
use App\Framework\HttpClient\Exception\CurlExecutionFailed;
use App\Framework\HttpClient\Exception\CurlNotInitialized;

final readonly class CurlHttpClient implements HttpClient
{
    public function __construct(
        private CurlResponseParser    $responseParser = new CurlResponseParser(),
        private AuthenticationHandler $authenticationHandler = new AuthenticationHandler(),
        private CurlRequestBuilder    $requestBuilder = new CurlRequestBuilder(),
    ) {
    }

    /**
     * @throws CurlExecutionFailed
     */
    public function send(ClientRequest $request): ClientResponse
    {
        // Initialize OOP curl handle
        $handle = new Handle();

        try {
            // Build options using HandleOption enum
            $options = $this->requestBuilder->buildOptions($request);

            // Handle authentication
            if ($request->options->auth !== null) {
                $authResult = $this->authenticationHandler->configure($request->options->auth, $request->headers);

                if ($authResult->headers !== $request->headers) {
                    $updatedRequest = $request->with(['headers' => $authResult->headers]);
                    $options = $this->requestBuilder->buildOptions($updatedRequest);
                }

                if (! empty($authResult->curlOptions)) {
                    $options = array_replace($options, $authResult->curlOptions);
                }
            }

            // Set all options using fluent API
            $handle->setOptions($options);

            // Execute request (automatically uses CURLOPT_RETURNTRANSFER)
            $rawResponse = $handle->fetch();

            // Parse response using underlying CurlHandle resource
            return $this->responseParser->parse($rawResponse, $handle->getResource());
        } catch (\Throwable $e) {
            // Wrap any exception in CurlExecutionFailed for backward compatibility
            throw new CurlExecutionFailed($e->getMessage(), $e->getCode(), $e);
        }




        /*
                // URL mit Query-Parametern verarbeiten
                $url = $request->url;
                if (!empty($request->options->query)) {
                    $separator = str_contains($url, '?') ? '&' : '?';
                    $url .= $separator . http_build_query($request->options->query);
                }

                $options = [
                    CURLOPT_URL => $url,
                    CURLOPT_CUSTOMREQUEST => $request->method->value,
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_HEADER => true,
                    CURLOPT_TIMEOUT => $request->options->timeout,
                    CURLOPT_CONNECTTIMEOUT => $request->options->connectTimeout,
                    CURLOPT_FOLLOWLOCATION => $request->options->followRedirects,
                    CURLOPT_MAXREDIRS => $request->options->maxRedirects,
                    CURLOPT_SSL_VERIFYPEER => $request->options->verifySsl,
                    CURLOPT_SSL_VERIFYHOST => $request->options->verifySsl ? 2 : 0,
                ];

                // User-Agent setzen wenn vorhanden
                if ($request->options->userAgent !== null) {
                    $options[CURLOPT_USERAGENT] = $request->options->userAgent;
                }

                // Proxy setzen wenn vorhanden
                if ($request->options->proxy !== null) {
                    $options[CURLOPT_PROXY] = $request->options->proxy;
                }

                // Authentifizierung einrichten
                if ($request->options->auth !== null) {
                    $this->setupAuthentication($ch, $request->options->auth, $request->headers);
                }

                // Request-Body verarbeiten
                if ($request->body !== '') {
                    $options[CURLOPT_POSTFIELDS] = $request->body;
                }

                // Headers formatieren und setzen
                if (count($request->headers->all()) > 0) {
                    $options[CURLOPT_HTTPHEADER] = HeaderManipulator::formatForCurl($request->headers);
                }

                curl_setopt_array($ch, $options);

                $raw = curl_exec($ch);

                if ($raw === false) {
                    throw new CurlExecutionFailed(curl_error($ch), curl_errno($ch));
                }

                $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
                $headersRaw = substr($raw, 0, $headerSize);
                $body = substr($raw, $headerSize);
                $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);

                $headers = HeaderManipulator::fromString($headersRaw);

                return new ClientResponse(
                    status: Status::from($status),
                    headers: $headers,
                    body: $body
                );*/
    }
}
