<?php

declare(strict_types=1);

namespace App\Framework\HttpClient;

use App\Framework\Http\Headers;
use App\Framework\Http\Method;

final readonly class ClientRequest
{
    public function __construct(
        public Method        $method,
        public string        $url,
        public Headers       $headers = new Headers(),
        public string|array  $body = '',
        public ClientOptions $options = new ClientOptions()
    ) {
    }

    /**
     * Erstellt eine neue Anfrage mit geänderten Parametern
     */
    public function with(array $parameters = []): self
    {
        return new self(
            method: $parameters['method'] ?? $this->method,
            url: $parameters['url'] ?? $this->url,
            headers: $parameters['headers'] ?? $this->headers,
            body: $parameters['body'] ?? $this->body,
            options: $parameters['options'] ?? $this->options
        );
    }

    /**
     * Erstellt eine Anfrage mit JSON-Body
     */
    public static function json(
        Method         $method,
        string         $url,
        array          $data,
        ?ClientOptions $options = null
    ): self {
        $headers = new Headers()->with('Content-Type', 'application/json');

        return new self(
            method: $method,
            url: $url,
            headers: $headers,
            body: json_encode($data, JSON_THROW_ON_ERROR),
            options: $options ?? new ClientOptions()
        );
    }

    /**
     * Erstellt eine Anfrage mit Form-Daten
     */
    public static function form(
        Method         $method,
        string         $url,
        array          $data,
        ?ClientOptions $options = null
    ): self {
        $headers = new Headers()->with('Content-Type', 'application/x-www-form-urlencoded');

        return new self(
            method: $method,
            url: $url,
            headers: $headers,
            body: http_build_query($data),
            options: $options ?? new ClientOptions()
        );
    }

    /**
     * Erstellt eine Anfrage mit Multipart-Form-Daten (für Datei-Uploads)
     */
    public static function multipart(
        Method         $method,
        string         $url,
        array          $data,
        array          $files = [],
        ?ClientOptions $options = null
    ): self {
        // Bei Multipart setzt cURL den Content-Type automatisch mit Boundary
        $headers = new Headers();

        // Transformiere Dateien in das cURL-Format für CURLOPT_POSTFIELDS
        $formData = $data;
        foreach ($files as $name => $filePath) {
            $formData[$name] = curl_file_create($filePath);
        }

        return new self(
            method: $method,
            url: $url,
            headers: $headers,
            body: $formData, // cURL verarbeitet das automatisch als Multipart
            options: $options ?? new ClientOptions()
        );
    }
}
