<?php
namespace Docuform\Api\Exception;

use League\OAuth2\Server\Exception\OAuthServerException;
use Docuform\Api\Logger;
use Throwable;

class ApiHttpAuthException extends \Exception
{
  /**
   * @var OAuthServerException
   */
  private OAuthServerException $oauthException;

  /**
   * @var string
   */
  protected string $logDescription = '';

  public function __construct(
    int $code = 400,
    ?string $error = null,
    ?string $errorDescription = null,
    ?string $hint = null,
    ?string $redirectUri = null,
    ?Logger $logger = null,
    ?string $logDescription = null,
    ?Throwable $previous = null
  ) {
    if (empty($error)) {
      $error = 'Authorization error';
    }

    if ($logger !== null && !empty($logDescription)) {
      $logger->error($logDescription);
    }

    if (empty($hint)) {
      $hint = null;
    }

    $this->logDescription = $logDescription ?? '';

    // Erstelle die interne OAuthServerException
    $this->oauthException = new OAuthServerException(
      $errorDescription ?? '',
      0,
      $error,
      $code,
      $hint,
      $redirectUri,
      $previous
    );

    // Initialisiere die parent Exception mit den gleichen Daten
    parent::__construct($errorDescription ?? $error, $code, $previous);
  }

  /**
   * Delegiert alle OAuth-spezifischen Methoden an die interne OAuthServerException
   */
  public function getErrorType(): string
  {
    return $this->oauthException->getErrorType();
  }

  /**
   * @return string|null
   */
  public function getHint(): ?string
  {
    return $this->oauthException->getHint();
  }

  /**
   * @return string|null
   */
  public function getRedirectUri(): ?string
  {
    return $this->oauthException->getRedirectUri();
  }

  /**
   * @return int
   */
  public function getHttpStatusCode(): int
  {
    return $this->oauthException->getHttpStatusCode();
  }

  /**
   * @return array
   */
  public function getPayload(): array
  {
    return $this->oauthException->getPayload();
  }

  /**
   * @return array
   */
  public function getHeaders(): array
  {
    return $this->oauthException->getHeaders();
  }

  /**
   * Gibt die interne OAuthServerException zurück, falls sie direkt benötigt wird
   *
   * @return OAuthServerException
   */
  public function getOAuthException(): OAuthServerException
  {
    return $this->oauthException;
  }

  /**
   * Get the log description
   *
   * @return string
   */
  public function getLogDescription(): string
  {
    return $this->logDescription;
  }

  /**
   * Für den Fall, dass Code diese Exception wie eine OAuthServerException behandeln muss
   */
  public function generateHttpResponse(\Psr\Http\Message\ResponseInterface $response): \Psr\Http\Message\ResponseInterface
  {
    return $this->oauthException->generateHttpResponse($response);
  }
}
