<?php

declare(strict_types=1);

namespace Autogedal\FeedMonitor\Model\Fetch;

use Autogedal\FeedMonitor\Model\Problem;

/**
 * Outcome of reading a feed: the content, or why there is none (connection / HTTP error, empty answer).
 */
class FetchResult
{
    public function __construct(
        private readonly string $url,
        private readonly ?string $body,
        private readonly ?string $problem,
        private readonly string $error,
        private readonly int $httpCode,
        private readonly int $attempts
    ) {
    }

    public function isOk(): bool
    {
        return $this->problem === null;
    }

    public function getBody(): string
    {
        return (string)$this->body;
    }

    /**
     * Problem::FETCH or Problem::EMPTY, null when the content was received.
     */
    public function getProblem(): ?string
    {
        return $this->problem;
    }

    /**
     * The error alone, without the host and attempts of getErrorMessage().
     */
    public function getError(): string
    {
        return $this->error;
    }

    public function getHttpCode(): int
    {
        return $this->httpCode;
    }

    public function getAttempts(): int
    {
        return $this->attempts;
    }

    /**
     * Text for logs and emails with only the host of the feed: tokens, keys and secret paths
     * (e.g. www.suportbicicleta.ro/feed/products/<hash>) stay out.
     */
    public function getErrorMessage(): string
    {
        if ($this->isOk()) {
            return '';
        }

        return sprintf('%s (%s, %d %s)', $this->error, self::hostOf($this->url), $this->attempts,
            $this->attempts === 1 ? 'incercare' : 'incercari');
    }

    public static function hostOf(string $url): string
    {
        return (string)(parse_url($url, PHP_URL_HOST) ?: 'adresa invalida');
    }

    public static function ok(string $url, string $body, int $httpCode, int $attempts): self
    {
        return new self($url, $body, null, '', $httpCode, $attempts);
    }

    public static function failed(string $url, string $problem, string $error, int $httpCode, int $attempts): self
    {
        return new self($url, null, $problem, $error, $httpCode, $attempts);
    }

    public static function empty(string $url, int $httpCode, int $attempts): self
    {
        return new self($url, null, Problem::EMPTY, 'Raspuns gol', $httpCode, $attempts);
    }
}
