<?php

declare(strict_types=1);

namespace App\Framework\Webhook\Sending;

/**
 * Result of webhook sending operation
 * Contains all information about the webhook request and response
 */
final readonly class WebhookSendResult
{
    public function __construct(
        public string $webhookId,
        public bool $success,
        public int $statusCode,
        public string $responseBody,
        public array $responseHeaders,
        public float $requestTime,
        public int $attempt = 1,
        public ?string $error = null
    ) {
    }

    /**
     * Check if webhook was sent successfully
     */
    public function isSuccessful(): bool
    {
        return $this->success;
    }

    /**
     * Check if webhook failed
     */
    public function isFailed(): bool
    {
        return ! $this->success;
    }

    /**
     * Check if failure was due to client error (4xx)
     */
    public function isClientError(): bool
    {
        return $this->statusCode >= 400 && $this->statusCode < 500;
    }

    /**
     * Check if failure was due to server error (5xx)
     */
    public function isServerError(): bool
    {
        return $this->statusCode >= 500;
    }

    /**
     * Check if request was rate limited
     */
    public function isRateLimited(): bool
    {
        return $this->statusCode === 429;
    }

    /**
     * Check if failure should be retried
     */
    public function shouldRetry(): bool
    {
        // Retry on server errors, rate limiting, or connection errors
        return $this->isServerError() || $this->isRateLimited() || $this->statusCode === 0;
    }

    /**
     * Get response as JSON array if possible
     */
    public function getJsonResponse(): ?array
    {
        if (empty($this->responseBody)) {
            return null;
        }

        try {
            return json_decode($this->responseBody, true, 512, JSON_THROW_ON_ERROR);
        } catch (\JsonException) {
            return null;
        }
    }

    /**
     * Get specific response header
     */
    public function getResponseHeader(string $header): ?string
    {
        $header = strtolower($header);

        foreach ($this->responseHeaders as $key => $value) {
            if (strtolower($key) === $header) {
                return is_array($value) ? $value[0] : $value;
            }
        }

        return null;
    }

    /**
     * Convert result to array for logging/serialization
     */
    public function toArray(): array
    {
        return [
            'webhook_id' => $this->webhookId,
            'success' => $this->success,
            'status_code' => $this->statusCode,
            'request_time' => $this->requestTime,
            'attempt' => $this->attempt,
            'error' => $this->error,
            'response_size' => strlen($this->responseBody),
            'has_json_response' => $this->getJsonResponse() !== null,
        ];
    }
}
