<?php
/**
 * Asset enqueue + runtime payload.
 *
 * @package Polanger_Shield
 */

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

class Polanger_Shield_Runtime {

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

  /**
   * Get singleton.
   *
   * @return Polanger_Shield_Runtime
   */
  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( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ), 99 );
  }

  /**
   * Enqueue builder/runtime assets.
   *
   * @return void
   */
  public function enqueue_assets() {
    if ( ! is_admin() ) {
      return;
    }

    if ( Polanger_Shield_Safe_Mode::is_active() ) {
      return;
    }

    $context = Polanger_Shield_Context::current();
    $current_user_id = get_current_user_id();
    $runtime_rules = $this->get_runtime_rules_for_user( $current_user_id, $context );

    if ( ! empty( $runtime_rules ) ) {
      wp_enqueue_style(
        'polanger-shield-runtime',
        POLANGER_SHIELD_URL . 'assets/css/shield-runtime.css',
        array(),
        POLANGER_SHIELD_VERSION
      );

      wp_enqueue_script(
        'polanger-shield-runtime',
        POLANGER_SHIELD_URL . 'assets/js/shield-runtime.js',
        array( 'jquery' ),
        POLANGER_SHIELD_VERSION,
        false
      );

      wp_localize_script(
        'polanger-shield-runtime',
        'polangerShieldRuntime',
        array(
          'rules' => $runtime_rules,
          'ajaxUrl' => admin_url( 'admin-ajax.php' ),
          'nonce'   => wp_create_nonce( 'polanger_shield_nonce' ),
          'canManage' => Polanger_Shield_Permissions::current_user_can_manage_shield( true ),
          'manageUrl' => admin_url( 'admin.php?page=polanger-shield' ),
          'i18n'  => array(
            'noteLabel' => __( 'Note', 'polanger-admin-menu-manager' ),
            'openNote'  => __( 'Open note', 'polanger-admin-menu-manager' ),
            'noteTitle' => __( 'Internal Note', 'polanger-admin-menu-manager' ),
            'noteHint'  => __( 'Visible only to selected administrators.', 'polanger-admin-menu-manager' ),
            'disableRule' => __( 'Disable Rule', 'polanger-admin-menu-manager' ),
            'editRule'    => __( 'Open Rule', 'polanger-admin-menu-manager' ),
            'viewDetails' => __( 'Manage Rules', 'polanger-admin-menu-manager' ),
            'ruleDisabled'=> __( 'Rule disabled.', 'polanger-admin-menu-manager' ),
            'actionFailed'=> __( 'Action failed.', 'polanger-admin-menu-manager' ),
          ),
        )
      );
    }

    if ( ! Polanger_Shield_Permissions::current_user_can_manage_shield( true ) ) {
      return;
    }

    $users = get_users(
      array(
        'role__in' => array( 'administrator' ),
        'orderby'  => 'display_name',
      )
    );

    $user_list = array();
    foreach ( $users as $user ) {
      $user_list[] = array(
        'id'    => (int) $user->ID,
        'label' => sprintf(
          /* translators: 1: display name, 2: email */
          __( '%1$s (%2$s)', 'polanger-admin-menu-manager' ),
          $user->display_name,
          $user->user_email
        ),
      );
    }

    wp_enqueue_style(
      'polanger-shield-builder',
      POLANGER_SHIELD_URL . 'assets/css/shield-builder.css',
      array(),
      POLANGER_SHIELD_VERSION
    );

    wp_enqueue_script(
      'polanger-shield-selector',
      POLANGER_SHIELD_URL . 'assets/js/selector-generator.js',
      array(),
      POLANGER_SHIELD_VERSION,
      true
    );

    wp_enqueue_script(
      'polanger-shield-builder',
      POLANGER_SHIELD_URL . 'assets/js/shield-builder.js',
      array( 'jquery', 'polanger-shield-selector' ),
      POLANGER_SHIELD_VERSION,
      true
    );

    $test_rule = null;
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    $test_rule_id = isset( $_GET['polanger_shield_test_rule'] ) ? absint( wp_unslash( $_GET['polanger_shield_test_rule'] ) ) : 0;
    if ( $test_rule_id ) {
      $candidate = Polanger_Shield_Rules::get_by_id( $test_rule_id );
      if ( $candidate && 'active' === (string) $candidate->status ) {
        $test_rule = array(
          'id'       => absint( $candidate->id ),
          'ruleType' => sanitize_key( (string) $candidate->rule_type ),
          'selector' => (string) $candidate->selector,
        );
      }
    }

    wp_localize_script(
      'polanger-shield-builder',
      'polangerShieldBuilder',
      array(
        'ajaxUrl' => admin_url( 'admin-ajax.php' ),
        'nonce'   => wp_create_nonce( 'polanger_shield_nonce' ),
        'context' => $context,
        'testRule' => $test_rule,
        'users'   => $user_list,
        'i18n'    => array(
          'saveFailed'         => __( 'Rule could not be saved.', 'polanger-admin-menu-manager' ),
          'saveSuccess'        => __( 'Rule saved successfully.', 'polanger-admin-menu-manager' ),
          'selectUsers'        => __( 'Select users', 'polanger-admin-menu-manager' ),
          'hideThisPage'       => __( 'Hide this page for selected users', 'polanger-admin-menu-manager' ),
          'blockUrlAccess'     => __( 'Block direct URL access', 'polanger-admin-menu-manager' ),
          'saveRule'           => __( 'Save Rule', 'polanger-admin-menu-manager' ),
          'cancel'             => __( 'Cancel', 'polanger-admin-menu-manager' ),
          'leaveNote'          => __( 'Leave note for selected users', 'polanger-admin-menu-manager' ),
          'notePlaceholder'    => __( 'Write your note...', 'polanger-admin-menu-manager' ),
          'selectorReliability'=> __( 'Selector reliability', 'polanger-admin-menu-manager' ),
          'selectedArea'       => __( 'Selected area', 'polanger-admin-menu-manager' ),
          'technicalSelector'  => __( 'Technical selector', 'polanger-admin-menu-manager' ),
          'pageBlockHelp'      => __( 'Selected users will not be able to open this page. If URL blocking is enabled, direct URL access is also denied.', 'polanger-admin-menu-manager' ),
          'elementHideHelp'    => __( 'Selected users will not see this area on this admin page.', 'polanger-admin-menu-manager' ),
          'noteHelp'           => __( 'Only selected users will see this note on the selected area.', 'polanger-admin-menu-manager' ),
          'selectUserWarning'  => __( 'Please select at least one user.', 'polanger-admin-menu-manager' ),
          'noteRequired'       => __( 'Please write a note before saving.', 'polanger-admin-menu-manager' ),
          'selectedUsersLabel' => __( 'Affected users', 'polanger-admin-menu-manager' ),
          'visibleUsersLabel'  => __( 'Users who can see this note', 'polanger-admin-menu-manager' ),
          'testModeApplied'    => __( 'Rule test mode: selected area is highlighted.', 'polanger-admin-menu-manager' ),
        ),
      )
    );
  }

  /**
   * Get runtime rules for current user/context.
   *
   * @param int   $user_id User ID.
   * @param array $context Context.
   * @return array
   */
  private function get_runtime_rules_for_user( $user_id, $context ) {
    $user_id = absint( $user_id );
    if ( ! $user_id ) {
      return array();
    }

    $output = array();

    $hide_rules = Polanger_Shield_Rules::get_active_rules_for_context( 'element_hide', $context );
    foreach ( $hide_rules as $rule ) {
      if ( ! Polanger_Shield_Permissions::is_user_targeted_by_rule( $rule, $user_id ) ) {
        continue;
      }

      $output[] = array(
        'id'       => absint( $rule->id ),
        'ruleType' => 'element_hide',
        'selector' => (string) $rule->selector,
      );
    }

    $note_rules = Polanger_Shield_Rules::get_active_rules_for_context( 'note', $context );
    foreach ( $note_rules as $rule ) {
      if ( ! Polanger_Shield_Permissions::can_user_see_note( $rule, $user_id ) ) {
        continue;
      }

      $output[] = array(
        'id'       => absint( $rule->id ),
        'ruleType' => 'note',
        'selector' => (string) $rule->selector,
        'note'     => wp_kses_post( (string) $rule->note ),
      );
    }

    return $output;
  }
}
