<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing

namespace MailPoet\Subscription;

if (!defined('ABSPATH')) exit;


use MailPoet\Config\Renderer as TemplateRenderer;
use MailPoet\Entities\SubscriberEntity;
use MailPoet\Logging\LoggerFactory;
use MailPoet\Settings\SettingsController;
use MailPoet\Subscribers\ConfirmationEmailMailer;
use MailPoet\Subscribers\SubscribersRepository;
use MailPoet\WP\Functions as WPFunctions;

class AdminUserSubscription {
  /** @var WPFunctions */
  private $wp;

  /** @var SettingsController */
  private $settings;

  /** @var SubscribersRepository */
  private $subscribersRepository;

  /** @var ConfirmationEmailMailer */
  private $confirmationEmailMailer;

  /** @var LoggerFactory */
  private $loggerFactory;

  /** @var TemplateRenderer */
  private $templateRenderer;

  public function __construct(
    WPFunctions $wp,
    SettingsController $settings,
    SubscribersRepository $subscribersRepository,
    ConfirmationEmailMailer $confirmationEmailMailer,
    LoggerFactory $loggerFactory,
    TemplateRenderer $templateRenderer
  ) {
    $this->wp = $wp;
    $this->settings = $settings;
    $this->subscribersRepository = $subscribersRepository;
    $this->confirmationEmailMailer = $confirmationEmailMailer;
    $this->loggerFactory = $loggerFactory;
    $this->templateRenderer = $templateRenderer;
  }

  /**
   * Set up hooks for the Add New User form in WordPress admin
   */
  public function setupHooks(): void {
    // Set up hooks for the Add New User form
    $this->wp->addAction('user_new_form', [$this, 'displaySubscriberStatusField']);

    // Use the lower priority filter instead of an action - this is simpler and more reliable
    $this->wp->addFilter('mailpoet_subscriber_data_before_save', [$this, 'modifySubscriberData'], 10, 1);

    // Add action to send confirmation email after user registration is complete
    $this->wp->addAction('user_register', [$this, 'maybeSendConfirmationEmail'], 30, 1);
  }

  /**
   * Display the subscriber status field on the Add New User form
   *
   * @param string $type The form context, 'add-new-user' for single site and network admin
   */
  public function displaySubscriberStatusField($type): void {
    // According to WordPress docs, the parameter is 'add-new-user' for single site and network admin
    if ($type !== 'add-new-user') {
      return;
    }

    $templateData = [
      'confirmationEnabled' => (bool)$this->settings->get('signup_confirmation.enabled', false),
      'statuses' => [
        'subscribed' => SubscriberEntity::STATUS_SUBSCRIBED,
        'unconfirmed' => SubscriberEntity::STATUS_UNCONFIRMED,
        'unsubscribed' => SubscriberEntity::STATUS_UNSUBSCRIBED,
      ],
    ];

    $renderedTemplate = $this->templateRenderer->render(
      'subscription/admin_user_status_field.html',
      $templateData
    );

    $allowedHtml = [
      'table' => ['class' => true],
      'tr' => [],
      'th' => ['scope' => true],
      'td' => [],
      'label' => ['for' => true],
      'select' => ['name' => true, 'id' => true],
      'option' => ['value' => true, 'selected' => true],
    ];
    // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
    echo $this->wp->wpKses($renderedTemplate, $allowedHtml);
  }

  /**
   * Modify subscriber data before save during user creation
   *
   * @param array $data The subscriber data
   * @return array Modified subscriber data
   */
  public function modifySubscriberData($data): array {
    // Only process during user creation in admin
    if (!$this->isAdminUserCreation()) {
      return $data;
    }

    // Check if our field was submitted
    if (!isset($_POST['mailpoet_subscriber_status']) || !is_string($_POST['mailpoet_subscriber_status'])) {
      return $data;
    }

    $status = sanitize_text_field($_POST['mailpoet_subscriber_status']);

    // Validate the status value
    $validStatuses = [
      SubscriberEntity::STATUS_SUBSCRIBED,
      SubscriberEntity::STATUS_UNCONFIRMED,
      SubscriberEntity::STATUS_UNSUBSCRIBED,
    ];

    if (!in_array($status, $validStatuses)) {
      return $data;
    }

    // Update the subscriber data
    $data['status'] = $status;
    $data['source'] = 'administrator';

    return $data;
  }

  /**
   * Send confirmation email if needed after user registration
   *
   * @param int $userId The WordPress user ID
   */
  public function maybeSendConfirmationEmail(int $userId): void {
    // Only process during user creation in admin
    if (!$this->isAdminUserCreation()) {
      return;
    }

    // Check if our field was submitted and is set to unconfirmed
    if (
        !isset($_POST['mailpoet_subscriber_status']) ||
        $_POST['mailpoet_subscriber_status'] !== SubscriberEntity::STATUS_UNCONFIRMED
    ) {
      return;
    }

    // Find the subscriber
    $subscriber = $this->subscribersRepository->findOneBy(['wpUserId' => $userId]);

    if (!$subscriber || $subscriber->getStatus() !== SubscriberEntity::STATUS_UNCONFIRMED) {
      return;
    }

    // Send confirmation email. Per-list confirmation settings are not resolved
    // here because admin-created users are subscribed via the WP Users segment.
    try {
      $this->confirmationEmailMailer->sendConfirmationEmailOnce($subscriber);
    } catch (\Exception $e) {
      // Log the error
      $logger = $this->loggerFactory->getLogger();
      $logger->error(
        __('Failed to send confirmation email for admin-created user', 'mailpoet'),
        ['user_id' => $userId, 'error' => $e->getMessage()]
      );
    }
  }

  /**
   * Check if we're in the context of admin user creation
   *
   * @return bool
   */
  private function isAdminUserCreation(): bool {
    // Check if we're in admin
    if (!$this->wp->isAdmin()) {
      return false;
    }

    // Check for the WordPress new user admin page
    global $pagenow;
    if ($pagenow !== 'user-new.php') {
      return false;
    }

    return true;
  }
}
