<?php
/**
 * reCAPTCHA Addon — Bootstrap
 *
 * Registers the addon on the Addons page, orchestrates all services, and
 * wires integrations with the Login Page module and Comment Security addon
 * exclusively via filters and actions — no core file logic is modified.
 *
 * Integration points
 * ──────────────────
 * 1. Login Page  — `polanger_effective_settings` filter (already present in
 *    the Login Page module) injects central keys and version into the
 *    login-page settings array so the existing render / verify flow works
 *    unchanged.
 *
 * 2. Comment forms — addon hooks WordPress's native `comment_form_after_fields`
 *    and `comment_form_logged_in_after` actions directly (priority 90) to
 *    render the widget.  When the Comment Security addon is active, the same
 *    output happens via `pdt_comment_security_extra_fields` (priority 10)
 *    and a static flag prevents double render.
 *
 * 3. Comment verification — `preprocess_comment` filter at priority 50 (before
 *    the Comment Security engine's priority 100) lets us hard-block on failure.
 *
 * @package Polanger_Dashboard_Tools
 */

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

require_once __DIR__ . '/includes/class-recaptcha-settings.php';
require_once __DIR__ . '/includes/class-recaptcha-service.php';
require_once __DIR__ . '/includes/class-recaptcha-page.php';

// ─────────────────────────────────────────────────────────────────────────────
// Always-on registrar (addon appears on Addons page even before activation)
// ─────────────────────────────────────────────────────────────────────────────

add_filter(
  'pdt_register_addons',
  /**
   * @param array $addons Addons registry.
   * @return array
   */
  function ( $addons ) {
    if ( ! is_array( $addons ) ) {
      $addons = array();
    }
    if ( ! isset( $addons['recaptcha'] ) ) {
      $addons['recaptcha'] = array(
        'title'       => __( 'reCAPTCHA', 'polanger-admin-menu-manager' ),
        'description' => __( 'Centrally manage Google reCAPTCHA v2/v3 keys and enable protection on login, registration, lost-password, and comment forms.', 'polanger-admin-menu-manager' ),
        'status'      => 'inactive',
        'slug'        => 'polanger-settings',
        'is_core'     => false,
      );
    }
    return $addons;
  }
);

// ─────────────────────────────────────────────────────────────────────────────
// Main orchestrator
// ─────────────────────────────────────────────────────────────────────────────

/**
 * reCAPTCHA Addon orchestrator.
 */
class PDT_Recaptcha {

  /**
   * Settings service.
   *
   * @var PDT_Recaptcha_Settings
   */
  private $settings;

  /**
   * Core service.
   *
   * @var PDT_Recaptcha_Service
   */
  private $service;

  /**
   * Admin page renderer.
   *
   * @var PDT_Recaptcha_Page
   */
  private $page;

  /**
   * Constructor.
   */
  public function __construct() {
    $this->settings = new PDT_Recaptcha_Settings();
    $this->service  = new PDT_Recaptcha_Service( $this->settings );
    $this->page     = new PDT_Recaptcha_Page( $this->settings, $this->service );

    // One-time migration from pdt_login_page_settings.
    add_action( 'init', array( $this->settings, 'maybe_migrate' ), 1 );

    // ── Admin tab ────────────────────────────────────────────────────────────
    add_filter( 'pdt_settings_tabs',      array( $this->page, 'register_tab' ) );
    add_filter( 'pdt_settings_tab_icons', array( $this->page, 'register_tab_icon' ) );
    add_action( 'pdt_settings_render_tab_recaptcha', array( $this->page, 'render_tab' ) );
    add_action( 'admin_init',             array( $this->page, 'maybe_handle_save' ) );
    add_action( 'admin_enqueue_scripts',  array( $this->page, 'enqueue_assets' ) );

    // ── Login Page integration ────────────────────────────────────────────────
    // Inject central keys into the Login Page module's effective settings.
    add_filter( 'polanger_effective_settings', array( $this, 'inject_login_page_keys' ), 10, 4 );

    // Enqueue reCAPTCHA JS on the login screen for the locations that are enabled.
    add_action( 'login_enqueue_scripts', array( $this, 'maybe_enqueue_login_script' ) );

    // ── Comment form integration ──────────────────────────────────────────────
    // Render widget — use comment_form_submit_field filter to place reCAPTCHA
    // right before the submit button (works for both guests and logged-in users).
    add_filter( 'comment_form_submit_field', array( $this, 'add_recaptcha_before_submit' ), 10, 2 );

    // Render widget — via Comment Security engine's extension hook.
    // Engine fires this inside render_protection_fields(); service sets a flag
    // so the direct hooks above become no-ops (prevents double output).
    add_action( 'pdt_comment_security_extra_fields', array( $this->service, 'render_for_comment_via_engine' ), 10 );

    // Verify reCAPTCHA before comment is stored.
    add_filter( 'preprocess_comment', array( $this, 'verify_comment_recaptcha' ), 50 );

    // Enqueue reCAPTCHA JS on frontend pages that have a comment form.
    add_action( 'wp_enqueue_scripts', array( $this, 'maybe_enqueue_comment_script' ) );
  }

  // ─────────────────────────────────────────────────────────────────────────
  // Login Page integration
  // ─────────────────────────────────────────────────────────────────────────

  /**
   * Inject reCAPTCHA keys from the central store into the Login Page module's
   * effective settings array.
   *
   * This filter is already called inside `PDT_Login_Page::get_settings()` so
   * no modification to that class is needed.
   *
   * @param array  $settings    Effective settings.
   * @param string $option_name Option name that was loaded.
   * @param array  $defaults    Default values for the option.
   * @param string $module      Module identifier.
   * @return array
   */
  public function inject_login_page_keys( $settings, $option_name, $defaults, $module ) {
    if ( 'login-page' !== $module ) {
      return $settings;
    }

    if ( ! $this->service->is_configured() ) {
      return $settings;
    }

    $cfg = $this->service->get_config();

    // Overlay keys and version; preserve all other login-page settings.
    $settings['recaptcha_site_key']   = $cfg['site_key'];
    $settings['recaptcha_secret_key'] = $cfg['secret_key'];
    $settings['recaptcha_version']    = $cfg['version'];

    // Sync per-location toggles from addon settings into login-page settings
    // so the Login Page module's own enable/disable toggles still govern
    // whether reCAPTCHA is active — but the addon is the single source of
    // truth for which locations are on.
    if ( $this->service->is_location_enabled( 'login' ) ) {
      $settings['recaptcha_login'] = '1';
    }
    if ( $this->service->is_location_enabled( 'register' ) ) {
      $settings['recaptcha_register'] = '1';
    }
    if ( $this->service->is_location_enabled( 'lostpassword' ) ) {
      $settings['recaptcha_lostpassword'] = '1';
    }

    // Ensure the global enable flag is on when the addon has keys and at
    // least one login-area location is enabled.
    $any_login_location = $this->service->is_location_enabled( 'login' )
      || $this->service->is_location_enabled( 'register' )
      || $this->service->is_location_enabled( 'lostpassword' );

    if ( $any_login_location ) {
      $settings['enable_recaptcha'] = '1';
    }

    return $settings;
  }

  /**
   * Enqueue the reCAPTCHA API script on the login page when needed.
   *
   * The Login Page module already handles this via `login_enqueue_scripts`,
   * but only when `enable_recaptcha` is truthy in its own settings. Since
   * we inject keys via the filter, the module's enqueue will fire correctly.
   * This method is a safety net for edge cases where the Login Page module
   * may not be active.
   *
   * @return void
   */
  public function maybe_enqueue_login_script() {
    // If the Login Page module is active it already handles enqueue; bail.
    if ( class_exists( 'PDT_Login_Page' ) ) {
      return;
    }

    $any_login_location = $this->service->is_location_enabled( 'login' )
      || $this->service->is_location_enabled( 'register' )
      || $this->service->is_location_enabled( 'lostpassword' );

    if ( ! $any_login_location || ! $this->service->is_configured() ) {
      return;
    }

    $this->service->enqueue_script();
  }

  // ─────────────────────────────────────────────────────────────────────────
  // Comment integration
  // ─────────────────────────────────────────────────────────────────────────

  /**
   * Add reCAPTCHA widget before the submit button in comment form.
   *
   * Hooked to `comment_form_submit_field` filter. This ensures the widget
   * appears right before the submit button for both guests and logged-in users.
   *
   * @param string $submit_field The submit button HTML.
   * @param array  $args         Comment form arguments.
   * @return string Modified submit field with reCAPTCHA prepended.
   */
  public function add_recaptcha_before_submit( $submit_field, $args ) {
    // Skip if already rendered via Comment Security engine
    if ( $this->service->was_comment_rendered() ) {
      return $submit_field;
    }

    if ( ! $this->service->is_location_enabled( 'comments' ) ) {
      return $submit_field;
    }

    if ( ! $this->service->is_configured() ) {
      return $submit_field;
    }

    $s = $this->settings->get_settings();
    if ( is_user_logged_in() && empty( $s['comment_logged_in'] ) ) {
      return $submit_field;
    }

    // Mark as rendered to prevent duplicates
    $this->service->mark_comment_rendered();

    // Capture the widget HTML
    ob_start();
    echo '<div class="pdt-recaptcha-comment-wrap" style="margin: 15px 0;">';
    $this->service->render_widget( 'comment' );
    echo '</div>';
    $recaptcha_html = ob_get_clean();

    return $recaptcha_html . $submit_field;
  }

  /**
   * Enqueue reCAPTCHA script on frontend pages that may have a comment form.
   *
   * @return void
   */
  public function maybe_enqueue_comment_script() {
    if ( ! $this->service->is_location_enabled( 'comments' ) ) {
      return;
    }
    if ( ! $this->service->is_configured() ) {
      return;
    }
    if ( ! is_singular() || ! comments_open() ) {
      return;
    }

    $this->service->enqueue_script();

    // For v3: enqueue the comment runtime script that fills the hidden token.
    $cfg = $this->service->get_config();
    if ( 'v3' === $cfg['version'] ) {
      $this->enqueue_v3_comment_script( $cfg['site_key'] );
    }
  }

  /**
   * Verify reCAPTCHA for incoming comments.
   *
   * Hooked at priority 50 — fires before the Comment Security engine (100).
   * Calls `wp_die()` on failure, matching WordPress core comment-spam handling.
   *
   * @param array $commentdata Incoming comment data.
   * @return array Unchanged comment data when verification passes.
   */
  public function verify_comment_recaptcha( $commentdata ) {
    if ( ! $this->service->is_location_enabled( 'comments' ) ) {
      return $commentdata;
    }

    if ( ! $this->service->is_configured() ) {
      return $commentdata;
    }

    // Skip pingback / trackback.
    $type = isset( $commentdata['comment_type'] ) ? $commentdata['comment_type'] : '';
    if ( ! in_array( $type, array( '', 'comment' ), true ) ) {
      return $commentdata;
    }

    $s = $this->settings->get_settings();
    if ( is_user_logged_in() && empty( $s['comment_logged_in'] ) ) {
      return $commentdata;
    }

    if ( ! $this->service->verify( 'comment' ) ) {
      wp_die(
        esc_html__( 'reCAPTCHA verification failed. Please go back and try again.', 'polanger-admin-menu-manager' ),
        esc_html__( 'Comment Error', 'polanger-admin-menu-manager' ),
        array(
          'response'  => 403,
          'back_link' => true,
        )
      );
    }

    return $commentdata;
  }

  // ─────────────────────────────────────────────────────────────────────────
  // Internal helpers
  // ─────────────────────────────────────────────────────────────────────────

  /**
   * Enqueue the v3 comment runtime script and pass the site key via
   * wp_localize_script() so the JS file contains no dynamic values.
   *
   * @param string $site_key Google site key.
   * @return void
   */
  private function enqueue_v3_comment_script( $site_key ) {
    wp_enqueue_script(
      'pdt-recaptcha-v3-comment',
      plugin_dir_url( __FILE__ ) . 'assets/js/recaptcha-v3-comment.js',
      array( 'pdt-recaptcha-api' ),
      PDT_VERSION,
      true
    );

    wp_localize_script(
      'pdt-recaptcha-v3-comment',
      'pdtRecaptchaV3Comment',
      array(
        'siteKey' => $site_key,
      )
    );
  }
}
