<?php

namespace Illuminate\Http\Client;

use GuzzleHttp\Psr7\Message;

class RequestException extends HttpClientException
{
    /**
     * The response instance.
     *
     * @var \Illuminate\Http\Client\Response
     */
    public $response;

    /**
     * The current truncation length for the exception message.
     *
     * @var int|false|null
     */
    public $truncateExceptionsAt;

    /**
     * The global truncation length for the exception message.
     *
     * @var int|false
     */
    public static $truncateAt = 120;

    /**
     * Whether the response has been summarized in the message.
     *
     * @var bool
     */
    public $hasBeenSummarized = false;

    /**
     * Create a new exception instance.
     *
     * @param  \Illuminate\Http\Client\Response  $response
     * @param  int|false|null  $truncateExceptionsAt
     */
    public function __construct(Response $response, $truncateExceptionsAt = null)
    {
        parent::__construct($this->prepareMessage($response), $response->status());

        $this->truncateExceptionsAt = $truncateExceptionsAt;

        $this->response = $response;
    }

    /**
     * Enable truncation of request exception messages.
     *
     * @return void
     */
    public static function truncate()
    {
        static::$truncateAt = 120;
    }

    /**
     * Set the truncation length for request exception messages.
     *
     * @param  int  $length
     * @return void
     */
    public static function truncateAt(int $length)
    {
        static::$truncateAt = $length;
    }

    /**
     * Disable truncation of request exception messages.
     *
     * @return void
     */
    public static function dontTruncate()
    {
        static::$truncateAt = false;
    }

    /**
     * Prepare the exception message.
     *
     * @return void
     */
    public function report(): void
    {
        if ($this->hasBeenSummarized) {
            return;
        }

        $this->message = $this->prepareMessage($this->response);

        $this->hasBeenSummarized = true;
    }

    /**
     * Prepare the exception message.
     *
     * @param  \Illuminate\Http\Client\Response  $response
     * @return string
     */
    protected function prepareMessage(Response $response)
    {
        $message = "HTTP request returned status code {$response->status()}";

        $truncateExceptionsAt = $this->truncateExceptionsAt ?? static::$truncateAt;

        $summary = is_int($truncateExceptionsAt)
            ? Message::bodySummary($response->toPsrResponse(), $truncateExceptionsAt)
            : Message::toString($response->toPsrResponse());

        return is_null($summary) ? $message : $message.":\n{$summary}\n";
    }
}
