<?php
/**
 * reCAPTCHA Addon — Settings Manager
 *
 * Owns the `pdt_recaptcha_settings` option and handles one-time
 * migration of keys previously stored in `pdt_login_page_settings`.
 *
 * @package Polanger_Dashboard_Tools
 */

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

/**
 * reCAPTCHA Settings.
 */
class PDT_Recaptcha_Settings {

  /**
   * Option name for central reCAPTCHA settings.
   *
   * @var string
   */
  const OPTION_NAME = 'pdt_recaptcha_settings';

  /**
   * Flag option name used to prevent repeated migration runs.
   *
   * @var string
   */
  const MIGRATION_FLAG = 'pdt_recaptcha_migrated';

  /**
   * Option name for the legacy login-page settings (migration source).
   *
   * @var string
   */
  const LEGACY_OPTION = 'pdt_login_page_settings';

  /**
   * Return normalized reCAPTCHA location keys and default states.
   *
   * This method must stay free of translation calls because login-page
   * settings can be resolved before `init`.
   *
   * @return array<string,string>
   */
  public function get_location_keys() {
    $locations = array(
      'login'             => '1',
      'register'          => '',
      'lostpassword'      => '',
      'comments'          => '',
      'comment_logged_in' => '',
    );

    $locations = apply_filters( 'pdt_recaptcha_location_keys', $locations );

    if ( ! is_array( $locations ) ) {
      return array();
    }

    $normalized = array();

    foreach ( $locations as $key => $default ) {
      $location_key = sanitize_key( $key );

      if ( '' === $location_key ) {
        continue;
      }

      $normalized[ $location_key ] = ! empty( $default ) ? '1' : '';
    }

    return $normalized;
  }

  /**
   * Return normalized reCAPTCHA location definitions.
   *
   * Addons can extend the UI list through the
   * `pdt_recaptcha_location_definitions` filter.
   *
   * @return array<string,array<string,string>>
   */
  public function get_location_definitions() {
    $location_keys = $this->get_location_keys();

    $locations = array(
      'login'             => array(
        'label'       => __( 'Login Form', 'polanger-admin-menu-manager' ),
        'description' => __( 'Add reCAPTCHA to the WordPress login form.', 'polanger-admin-menu-manager' ),
        'default'     => isset( $location_keys['login'] ) ? $location_keys['login'] : '1',
      ),
      'register'          => array(
        'label'       => __( 'Registration Form', 'polanger-admin-menu-manager' ),
        'description' => __( 'Add reCAPTCHA to the user registration form.', 'polanger-admin-menu-manager' ),
        'default'     => isset( $location_keys['register'] ) ? $location_keys['register'] : '',
      ),
      'lostpassword'      => array(
        'label'       => __( 'Lost Password Form', 'polanger-admin-menu-manager' ),
        'description' => __( 'Add reCAPTCHA to the lost password / password reset form.', 'polanger-admin-menu-manager' ),
        'default'     => isset( $location_keys['lostpassword'] ) ? $location_keys['lostpassword'] : '',
      ),
      'comments'          => array(
        'label'       => __( 'Comment Forms', 'polanger-admin-menu-manager' ),
        'description' => __( 'Add reCAPTCHA to public comment forms on posts and pages.', 'polanger-admin-menu-manager' ),
        'default'     => isset( $location_keys['comments'] ) ? $location_keys['comments'] : '',
      ),
      'comment_logged_in' => array(
        'label'       => __( 'Comments - Also enforce for logged-in users', 'polanger-admin-menu-manager' ),
        'description' => __( 'By default comment reCAPTCHA applies only to guests. Enable this to also enforce it for authenticated users.', 'polanger-admin-menu-manager' ),
        'default'     => isset( $location_keys['comment_logged_in'] ) ? $location_keys['comment_logged_in'] : '',
      ),
    );

    $locations = apply_filters( 'pdt_recaptcha_location_definitions', $locations, $location_keys );

    // Backward compatibility for older integrations that extended the UI list
    // through the original filter name.
    $locations = apply_filters( 'pdt_recaptcha_locations', $locations, $location_keys );

    if ( ! is_array( $locations ) ) {
      return array();
    }

    $normalized = array();

    foreach ( $locations as $key => $location ) {
      $location_key = sanitize_key( $key );

      if ( '' === $location_key || ! is_array( $location ) ) {
        continue;
      }

      $default = isset( $location_keys[ $location_key ] ) ? $location_keys[ $location_key ] : '';

      $normalized[ $location_key ] = array(
        'label'       => isset( $location['label'] ) ? (string) $location['label'] : $location_key,
        'description' => isset( $location['description'] ) ? (string) $location['description'] : '',
        'default'     => ! empty( $location['default'] ) || ! empty( $default ) ? '1' : '',
      );
    }

    foreach ( $location_keys as $location_key => $default ) {
      if ( isset( $normalized[ $location_key ] ) ) {
        continue;
      }

      $normalized[ $location_key ] = array(
        'label'       => $location_key,
        'description' => '',
        'default'     => ! empty( $default ) ? '1' : '',
      );
    }

    return $normalized;
  }

  /**
   * Return settings with defaults applied.
   *
   * @return array
   */
  public function get_settings() {
    $defaults = $this->get_defaults();
    $stored   = get_option( self::OPTION_NAME, array() );

    if ( ! is_array( $stored ) ) {
      $stored = array();
    }

    return wp_parse_args( $stored, $defaults );
  }

  /**
   * Save sanitized settings.
   *
   * @param array $raw Raw input data.
   * @return bool
   */
  public function save_settings( $raw ) {
    if ( ! is_array( $raw ) ) {
      return false;
    }

    $sanitized = $this->sanitize_settings( $raw );
    return update_option( self::OPTION_NAME, $sanitized );
  }

  /**
   * Return default values.
   *
   * @return array
   */
  public function get_defaults() {
    $defaults = array(
      'site_key'       => '',
      'secret_key'     => '',
      'version'        => 'v2',
      'v3_threshold'   => 0.5,
    );

    foreach ( $this->get_location_keys() as $location_key => $default ) {
      $defaults[ $location_key ] = ! empty( $default ) ? '1' : '';
    }

    return $defaults;
  }

  /**
   * Sanitize raw input.
   *
   * @param array $raw Raw form data.
   * @return array
   */
  public function sanitize_settings( $raw ) {
    $sanitized = array();

    $sanitized['site_key']   = isset( $raw['site_key'] )   ? sanitize_text_field( $raw['site_key'] )   : '';
    $sanitized['secret_key'] = isset( $raw['secret_key'] ) ? sanitize_text_field( $raw['secret_key'] ) : '';

    $sanitized['version'] = isset( $raw['version'] ) && in_array( $raw['version'], array( 'v2', 'v3' ), true )
      ? $raw['version']
      : 'v2';

    $raw_threshold           = isset( $raw['v3_threshold'] ) ? (float) $raw['v3_threshold'] : 0.5;
    $sanitized['v3_threshold'] = max( 0.0, min( 1.0, $raw_threshold ) );

    foreach ( array_keys( $this->get_location_keys() ) as $location ) {
      $sanitized[ $location ] = ! empty( $raw[ $location ] ) ? '1' : '';
    }

    return $sanitized;
  }

  /**
   * Run one-time migration from legacy login-page settings.
   *
   * Copies `recaptcha_site_key`, `recaptcha_secret_key`, and
   * `recaptcha_version` from `pdt_login_page_settings` into this option
   * (only if the central option does not already have keys).
   *
   * @return void
   */
  public function maybe_migrate() {
    if ( get_option( self::MIGRATION_FLAG ) ) {
      return;
    }

    // Mark migration as done immediately to prevent re-runs on error.
    update_option( self::MIGRATION_FLAG, '1' );

    $legacy = get_option( self::LEGACY_OPTION, array() );
    if ( ! is_array( $legacy ) ) {
      return;
    }

    $legacy_site_key   = isset( $legacy['recaptcha_site_key'] )   ? trim( $legacy['recaptcha_site_key'] )   : '';
    $legacy_secret_key = isset( $legacy['recaptcha_secret_key'] ) ? trim( $legacy['recaptcha_secret_key'] ) : '';

    if ( '' === $legacy_site_key && '' === $legacy_secret_key ) {
      // Nothing useful to migrate.
      return;
    }

    // Only import if the central store is still empty.
    $current = get_option( self::OPTION_NAME, array() );
    if ( is_array( $current ) && ! empty( $current['site_key'] ) ) {
      return;
    }

    $migrated                  = $this->get_defaults();
    $migrated['site_key']      = sanitize_text_field( $legacy_site_key );
    $migrated['secret_key']    = sanitize_text_field( $legacy_secret_key );
    $migrated['version']       = isset( $legacy['recaptcha_version'] ) && 'v3' === $legacy['recaptcha_version'] ? 'v3' : 'v2';
    $migrated['login']         = ! empty( $legacy['recaptcha_login'] )        ? '1' : '';
    $migrated['register']      = ! empty( $legacy['recaptcha_register'] )     ? '1' : '';
    $migrated['lostpassword']  = ! empty( $legacy['recaptcha_lostpassword'] ) ? '1' : '';

    update_option( self::OPTION_NAME, $migrated );
  }
}
