<?php
/**
 * AJAX endpoints.
 *
 * @package Polanger_Shield
 */

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

class Polanger_Shield_Ajax {

  /**
   * Singleton.
   *
   * @var Polanger_Shield_Ajax|null
   */
  private static $instance = null;

  /**
   * Get singleton.
   *
   * @return Polanger_Shield_Ajax
   */
  public static function instance() {
    if ( null === self::$instance ) {
      self::$instance = new self();
    }

    return self::$instance;
  }

  /**
   * Register hooks.
   *
   * @return void
   */
  public function register_hooks() {
    add_action( 'wp_ajax_polanger_shield_save_rule', array( $this, 'save_rule' ) );
    add_action( 'wp_ajax_polanger_shield_disable_rule', array( $this, 'disable_rule' ) );
  }

  /**
   * Save rule from floating builder.
   *
   * @return void
   */
  public function save_rule() {
    check_ajax_referer( 'polanger_shield_nonce', 'nonce' );

    if ( ! Polanger_Shield_Permissions::current_user_can_manage_shield( true ) ) {
      wp_send_json_error(
        array(
          'message' => __( 'Permission denied.', 'polanger-admin-menu-manager' ),
        ),
        403
      );
    }

    $rule_type = isset( $_POST['rule_type'] ) ? sanitize_key( wp_unslash( $_POST['rule_type'] ) ) : '';
    $rule_type = Polanger_Shield_Rules::sanitize_rule_type( $rule_type );
    if ( '' === $rule_type ) {
      wp_send_json_error(
        array(
          'message' => __( 'Invalid rule type.', 'polanger-admin-menu-manager' ),
        ),
        400
      );
    }

    $context = array(
      'screen_id'   => isset( $_POST['context_screen_id'] ) ? sanitize_text_field( wp_unslash( $_POST['context_screen_id'] ) ) : '',
      'page_hook'   => isset( $_POST['context_page_hook'] ) ? sanitize_text_field( wp_unslash( $_POST['context_page_hook'] ) ) : '',
      'page_slug'   => isset( $_POST['context_page_slug'] ) ? sanitize_text_field( wp_unslash( $_POST['context_page_slug'] ) ) : '',
      'request_uri' => isset( $_POST['context_request_uri'] ) ? sanitize_text_field( wp_unslash( $_POST['context_request_uri'] ) ) : '',
    );

    if ( empty( $context['screen_id'] ) && empty( $context['page_hook'] ) && empty( $context['page_slug'] ) && empty( $context['request_uri'] ) ) {
      $context = Polanger_Shield_Context::current();
    }
    $selector = isset( $_POST['selector'] ) ? wp_unslash( $_POST['selector'] ) : '';
    $selector = Polanger_Shield_Rules::sanitize_selector( $selector );
    $note = isset( $_POST['note'] ) ? wp_unslash( $_POST['note'] ) : '';
    $note = trim( (string) $note );
    $rule_meta = array();
    if ( class_exists( 'Polanger_Shield_Demo_Lock' ) && isset( $_POST['rule_meta'] ) ) {
      $rule_meta = Polanger_Shield_Demo_Lock::sanitize_rule_meta( wp_unslash( $_POST['rule_meta'] ) );
    }
    $target_users = isset( $_POST['target_user_ids'] ) ? array_values( array_unique( array_map( 'absint', (array) wp_unslash( $_POST['target_user_ids'] ) ) ) ) : array();
    $note_visible_user_ids = isset( $_POST['note_visible_user_ids'] ) ? array_values( array_unique( array_map( 'absint', (array) wp_unslash( $_POST['note_visible_user_ids'] ) ) ) ) : array();

    if ( in_array( $rule_type, array( 'element_hide', 'note' ), true ) && '' === $selector ) {
      wp_send_json_error(
        array(
          'message' => __( 'A valid target area is required for this rule.', 'polanger-admin-menu-manager' ),
        ),
        400
      );
    }

    if ( in_array( $rule_type, array( 'page_block', 'element_hide', 'demo_lock' ), true ) && empty( $target_users ) ) {
      wp_send_json_error(
        array(
          'message' => __( 'Please select at least one affected user.', 'polanger-admin-menu-manager' ),
        ),
        400
      );
    }

    if ( 'note' === $rule_type ) {
      if ( empty( $note_visible_user_ids ) ) {
        wp_send_json_error(
          array(
            'message' => __( 'Please select at least one user who can see the note.', 'polanger-admin-menu-manager' ),
          ),
          400
        );
      }

      if ( '' === trim( wp_strip_all_tags( $note ) ) ) {
        wp_send_json_error(
          array(
            'message' => __( 'Please write a note before saving.', 'polanger-admin-menu-manager' ),
          ),
          400
        );
      }
    }

    $rule_id = Polanger_Shield_Rules::insert(
      array(
        'rule_type'             => $rule_type,
        'screen_id'             => $context['screen_id'],
        'page_hook'             => $context['page_hook'],
        'page_slug'             => $context['page_slug'],
        'request_uri'           => $context['request_uri'],
        'selector'              => $selector,
        'selector_strength'     => isset( $_POST['selector_strength'] ) ? absint( wp_unslash( $_POST['selector_strength'] ) ) : 0,
        'note'                  => $note,
        'rule_meta'             => $rule_meta,
        'target_user_ids'       => $target_users,
        'note_visible_user_ids' => $note_visible_user_ids,
        'block_url'             => ! empty( $_POST['block_url'] ),
        'created_by'            => get_current_user_id(),
      )
    );

    if ( ! $rule_id ) {
      wp_send_json_error(
        array(
          'message' => __( 'Rule could not be saved.', 'polanger-admin-menu-manager' ),
        ),
        500
      );
    }

    Polanger_Shield_Activity::log(
      'shield_rule_created',
      array(
        'object_type' => 'shield_rule',
        'object_id'   => $rule_id,
        'meta'        => array(
          'rule_type' => $rule_type,
        ),
      )
    );

    wp_send_json_success(
      array(
        'id'      => $rule_id,
        'message' => __( 'Rule saved.', 'polanger-admin-menu-manager' ),
      )
    );
  }

  /**
   * Disable rule quickly from runtime context menu.
   *
   * @return void
   */
  public function disable_rule() {
    check_ajax_referer( 'polanger_shield_nonce', 'nonce' );

    if ( ! Polanger_Shield_Permissions::current_user_can_manage_shield( true ) ) {
      wp_send_json_error(
        array( 'message' => __( 'Permission denied.', 'polanger-admin-menu-manager' ) ),
        403
      );
    }

    $rule_id = isset( $_POST['rule_id'] ) ? absint( wp_unslash( $_POST['rule_id'] ) ) : 0;
    if ( ! $rule_id ) {
      wp_send_json_error(
        array( 'message' => __( 'Invalid rule ID.', 'polanger-admin-menu-manager' ) ),
        400
      );
    }

    if ( ! Polanger_Shield_Rules::disable( $rule_id ) ) {
      wp_send_json_error(
        array( 'message' => __( 'Rule could not be disabled.', 'polanger-admin-menu-manager' ) ),
        500
      );
    }

    Polanger_Shield_Activity::log(
      'shield_rule_disabled',
      array(
        'object_type' => 'shield_rule',
        'object_id'   => $rule_id,
      )
    );

    wp_send_json_success(
      array(
        'message' => __( 'Rule disabled.', 'polanger-admin-menu-manager' ),
      )
    );
  }
}
