<?php

declare(strict_types=1);

namespace Drupal\flowdrop\Form;

use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Form\FormStateInterface;

/**
 * Add/edit form for trusted workflow-bundle publishers.
 *
 * @internal
 *   This class is not part of the public API and may change without notice.
 */
final class FlowDropTrustedPublisherForm extends EntityForm {

  /**
   * {@inheritdoc}
   *
   * @param array<string, mixed> $form
   *   The form structure.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return array<string, mixed>
   *   The form structure.
   */
  public function form(array $form, FormStateInterface $form_state): array {
    $form = parent::form($form, $form_state);

    /** @var \Drupal\flowdrop\FlowDropTrustedPublisherInterface $entity */
    $entity = $this->entity;

    $form['label'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Publisher name'),
      '#description' => $this->t('A human-readable name for this publisher, e.g. "FlowDrop Marketplace".'),
      '#default_value' => $entity->label(),
      '#required' => TRUE,
      '#maxlength' => 255,
    ];

    $form['id'] = [
      '#type' => 'machine_name',
      '#title' => $this->t('Key ID'),
      '#description' => $this->t('The publisher key id. A bundle signature is trusted only when its key_id matches an enabled publisher.'),
      '#default_value' => $entity->id(),
      '#disabled' => !$entity->isNew(),
      '#machine_name' => [
        'exists' => '\Drupal\flowdrop\Entity\FlowDropTrustedPublisher::load',
        'source' => ['label'],
      ],
    ];

    $form['public_key'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Public key (base64)'),
      '#description' => $this->t("The publisher's base64-encoded Ed25519 public key. Paste exactly as supplied by the publisher."),
      '#default_value' => $entity->getPublicKey(),
      '#required' => TRUE,
      '#rows' => 2,
    ];

    $form['enabled'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Enabled'),
      '#description' => $this->t('Only enabled publishers grant trust. Disable to revoke trust without deleting the key.'),
      '#default_value' => $entity->isNew() ? TRUE : $entity->isEnabled(),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   *
   * @param array $form
   *   The form structure.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   */
  public function validateForm(array &$form, FormStateInterface $form_state): void {
    parent::validateForm($form, $form_state);

    $value = trim((string) $form_state->getValue('public_key'));
    $decoded = base64_decode($value, TRUE);
    if ($decoded === FALSE) {
      $form_state->setErrorByName('public_key', $this->t('The public key is not valid base64.'));
      return;
    }
    if (strlen($decoded) !== SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES) {
      $form_state->setErrorByName('public_key', $this->t('An Ed25519 public key must decode to @bytes bytes; this one is @actual.', [
        '@bytes' => SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES,
        '@actual' => strlen($decoded),
      ]));
    }
  }

  /**
   * {@inheritdoc}
   *
   * @param array<string, mixed> $form
   *   The form structure.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return int
   *   The save result.
   */
  public function save(array $form, FormStateInterface $form_state): int {
    $result = parent::save($form, $form_state);

    $this->messenger()->addStatus($this->t('Trusted publisher %label saved.', [
      '%label' => $this->entity->label(),
    ]));
    $form_state->setRedirectUrl($this->entity->toUrl('collection'));

    return $result;
  }

}
