<?php

declare(strict_types=1);

namespace Drupal\flowdrop\Service\Bundle;

/**
 * Outcome of verifying a workflow bundle's signature.
 *
 * Three terminal states:
 * - trusted: signature is valid AND was produced by an enabled trusted
 *   publisher whose key resolved.
 * - untrusted: the bundle is signed, but the signature does not verify, or the
 *   publisher is unknown/disabled. Import is blocked unless the caller holds
 *   the override permission.
 * - unsigned: the bundle carries no signature envelope at all.
 *
 * @internal
 */
final class VerificationResult {

  public const TRUSTED = 'trusted';
  public const UNTRUSTED = 'untrusted';
  public const UNSIGNED = 'unsigned';

  /**
   * Constructs a VerificationResult.
   *
   * @param string $status
   *   One of the status constants.
   * @param string|null $keyId
   *   The publisher key id the signature claimed, if any.
   * @param string|null $reason
   *   Human-readable explanation for a non-trusted outcome.
   */
  private function __construct(
    private readonly string $status,
    private readonly ?string $keyId = NULL,
    private readonly ?string $reason = NULL,
  ) {}

  /**
   * Creates a trusted result.
   *
   * @param string $keyId
   *   The publisher key id that signed the bundle.
   *
   * @return self
   *   The verification result.
   */
  public static function trusted(string $keyId): self {
    return new self(self::TRUSTED, $keyId);
  }

  /**
   * Creates an untrusted result.
   *
   * @param string $reason
   *   Why the bundle is untrusted.
   * @param string|null $keyId
   *   The claimed publisher key id, if the bundle named one.
   *
   * @return self
   *   The verification result.
   */
  public static function untrusted(string $reason, ?string $keyId = NULL): self {
    return new self(self::UNTRUSTED, $keyId, $reason);
  }

  /**
   * Creates an unsigned result.
   *
   * @return self
   *   The verification result.
   */
  public static function unsigned(): self {
    return new self(self::UNSIGNED, NULL, 'Bundle carries no signature.');
  }

  /**
   * Whether the bundle is signed by a trusted, enabled publisher.
   *
   * @return bool
   *   TRUE only for the trusted state.
   */
  public function isTrusted(): bool {
    return $this->status === self::TRUSTED;
  }

  /**
   * Gets the status.
   *
   * @return string
   *   One of the status constants.
   */
  public function getStatus(): string {
    return $this->status;
  }

  /**
   * Gets the claimed publisher key id.
   *
   * @return string|null
   *   The key id, or NULL when unsigned.
   */
  public function getKeyId(): ?string {
    return $this->keyId;
  }

  /**
   * Gets the reason for a non-trusted outcome.
   *
   * @return string|null
   *   The reason, or NULL when trusted.
   */
  public function getReason(): ?string {
    return $this->reason;
  }

}
