<?php
namespace PayCal\Admin;

defined('ABSPATH') || exit;

use PayCal\Permissions\Access;
use PayCal\Permissions\PermissionsStore;

class Page_Permissions {
  public static function render(): void {
    Access::enforce('permissions');

    self::maybe_handle_setup();
    self::maybe_handle_unlock();
    self::maybe_handle_lock();
    self::maybe_handle_secret_change();

    echo '<div class="wrap paycal-wrap">';
    echo '  <section class="paycal-header">';
    echo '    <div class="paycal-hero-copy">';
    echo '      <span class="paycal-eyebrow">PayCal</span>';
    echo '      <h1>ניהול הרשאות</h1>';
    echo '      <p>שליטה פשוטה בגישה למסכים המרכזיים של התוסף.</p>';
    echo '    </div>';
    echo '  </section>';

    self::render_notices();

    if (!PermissionsStore::has_permissions_lock()) {
      self::render_setup_screen();
      echo '</div>';
      return;
    }

    if (!PermissionsStore::current_user_is_verified()) {
      self::render_unlock_screen();
      echo '</div>';
      return;
    }

    self::maybe_save();
    self::render_management_screen();
    echo '</div>';
  }

  private static function render_notices(): void {
    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin notice selector; no state change is performed.
    $notice = isset($_GET['paycal_notice']) ? sanitize_key(wp_unslash($_GET['paycal_notice'])) : '';
    $map = [
      'saved' => ['success', 'ההרשאות נשמרו בהצלחה.'],
      'security_saved' => ['success', 'הגישה למסך נשמרה בהצלחה.'],
      'unlocked' => ['success', 'הגישה אושרה בהצלחה.'],
      'secret_changed' => ['success', 'קוד הכניסה עודכן בהצלחה.'],
      'locked' => ['success', 'המסך ננעל מחדש.'],
      'bad_secret' => ['error', 'קוד הכניסה שהוזן אינו נכון.'],
      'secret_mismatch' => ['error', 'שני השדות של קוד הכניסה חייבים להיות זהים.'],
      'secret_short' => ['error', 'יש לבחור קוד באורך 6 תווים לפחות.'],
    ];

    if (isset($map[$notice])) {
      echo '<div class="notice notice-' . esc_attr($map[$notice][0]) . ' is-dismissible"><p>' . esc_html($map[$notice][1]) . '</p></div>';
    }
  }

  private static function render_setup_screen(): void {
    echo '<div class="paycal-card" style="margin-top:20px;max-width:760px;">';
    echo '  <div class="paycal-section-head"><div><h2>הגנה על מסך ההרשאות</h2><p class="paycal-muted">כדי לפתוח את המסך הזה, נדרש קוד כניסה נוסף.</p></div></div>';
    echo '  <form method="post" action="' . esc_url(admin_url('admin.php?page=paycal-permissions')) . '">';
    wp_nonce_field('paycal_permissions_setup', 'paycal_permissions_setup_nonce');
    echo '    <table class="form-table" role="presentation">';
    echo '      <tr><th scope="row"><label for="paycal_permissions_secret">קוד כניסה</label></th><td><input type="password" class="regular-text" id="paycal_permissions_secret" name="paycal_permissions_secret" autocomplete="new-password" required><p class="description">בחרי קוד ייעודי למסך הזה בלבד, באורך 6 תווים לפחות.</p></td></tr>';
    echo '      <tr><th scope="row"><label for="paycal_permissions_secret_confirm">אימות קוד</label></th><td><input type="password" class="regular-text" id="paycal_permissions_secret_confirm" name="paycal_permissions_secret_confirm" autocomplete="new-password" required></td></tr>';
    echo '    </table>';
    submit_button('שמירת קוד כניסה');
    echo '  </form>';
    echo '</div>';
  }

  private static function render_unlock_screen(): void {
    echo '<div class="paycal-card" style="margin-top:20px;max-width:760px;">';
    echo '  <div class="paycal-section-head"><div><h2>כניסה למסך ההרשאות</h2><p class="paycal-muted">יש להזין את קוד הכניסה כדי להמשיך.</p></div></div>';
    echo '  <form method="post" action="' . esc_url(admin_url('admin.php?page=paycal-permissions')) . '">';
    wp_nonce_field('paycal_permissions_unlock', 'paycal_permissions_unlock_nonce');
    echo '    <table class="form-table" role="presentation">';
    echo '      <tr><th scope="row"><label for="paycal_permissions_unlock_secret">קוד כניסה</label></th><td><input type="password" class="regular-text" id="paycal_permissions_unlock_secret" name="paycal_permissions_unlock_secret" autocomplete="current-password" required><p class="description">לאחר אימות, המסך יישאר פתוח למשך 15 דקות.</p></td></tr>';
    echo '    </table>';
    submit_button('כניסה');
    echo '  </form>';
    echo '</div>';
  }

  private static function render_management_screen(): void {
    $caps = PermissionsStore::CAPS;
    $data = PermissionsStore::get();
    $wp_roles = wp_roles();
    $roles = $wp_roles ? $wp_roles->roles : [];
    $managed_users = PermissionsStore::get_managed_users();

    echo '  <div class="paycal-card" style="margin-top:20px;">';
    echo '    <div class="paycal-section-head"><div><h2>אבטחה</h2><p class="paycal-muted">אפשר לנעול את המסך או לעדכן את קוד הכניסה בכל רגע.</p></div></div>';
    echo '    <div style="display:flex;gap:12px;flex-wrap:wrap;align-items:flex-start;">';
    echo '      <form method="post" action="' . esc_url(admin_url('admin.php?page=paycal-permissions')) . '">';
    wp_nonce_field('paycal_permissions_lock', 'paycal_permissions_lock_nonce');
    submit_button('נעילה מיידית', 'secondary', 'submit', false);
    echo '      </form>';
    echo '      <form method="post" action="' . esc_url(admin_url('admin.php?page=paycal-permissions')) . '">';
    wp_nonce_field('paycal_permissions_change_secret', 'paycal_permissions_change_secret_nonce');
    echo '        <input type="password" class="regular-text" name="paycal_permissions_new_secret" placeholder="קוד חדש" autocomplete="new-password" required> ';
    echo '        <input type="password" class="regular-text" name="paycal_permissions_new_secret_confirm" placeholder="אימות קוד חדש" autocomplete="new-password" required> ';
    submit_button('עדכון קוד כניסה', 'secondary', 'submit', false);
    echo '      </form>';
    echo '    </div>';
    echo '  </div>';

    echo '  <form method="post" action="' . esc_url(admin_url('admin.php?page=paycal-permissions')) . '">';
    wp_nonce_field('paycal_permissions_save', 'paycal_permissions_nonce');

    echo '    <div class="paycal-card" style="margin-top:20px;">';
    echo '      <div class="paycal-section-head"><div><h2>הרשאות לפי תפקיד</h2><p class="paycal-muted">הגדרה ברמת תפקיד משפיעה על כל המשתמשים באותו תפקיד.</p></div></div>';
    echo '      <div style="overflow-x:auto;">';
    echo '        <table class="widefat striped">';
    echo '          <thead><tr><th>תפקיד</th>';
    foreach ($caps as $cap_label) {
      echo '            <th>' . esc_html($cap_label) . '</th>';
    }
    echo '          </tr></thead><tbody>';

    foreach ($roles as $role_key => $role_data) {
      echo '          <tr>';
      echo '            <td><strong>' . esc_html($role_data['name']) . '</strong></td>';
      foreach (array_keys($caps) as $cap_key) {
        $checked = !empty($data['roles'][$role_key][$cap_key]);
        echo '          <td><label><input type="checkbox" name="paycal_roles[' . esc_attr($role_key) . '][' . esc_attr($cap_key) . ']" value="1" ' . checked($checked, true, false) . '> כן</label></td>';
      }
      echo '          </tr>';
    }

    echo '          </tbody></table>';
    echo '      </div>';
    echo '    </div>';

    echo '    <div class="paycal-card" style="margin-top:20px;">';
    echo '      <div class="paycal-section-head"><div><h2>משתמשים מותאמים</h2><p class="paycal-muted">אפשר להוסיף משתמשים ספציפיים ולהגדיר להם הרשאות באופן ידני.</p></div></div>';
    echo '      <p><label for="paycal_user_ids"><strong>משתמשים לעריכה</strong></label><br>';
    echo '      <input type="text" id="paycal_user_ids" name="paycal_user_ids" class="regular-text" placeholder="למשל: 2,5,18">';
    echo '      <br><span class="description">הזיני מזהי משתמשים מופרדים בפסיקים כדי להוסיף אותם לטבלה.</span></p>';

    $extra_users = self::parse_requested_users();
    foreach ($extra_users as $extra_user) {
      $managed_users[(int) $extra_user->ID] = $extra_user;
    }

    if (empty($managed_users)) {
      echo '      <p>עדיין לא נוספו משתמשים מותאמים.</p>';
    } else {
      echo '      <div style="overflow-x:auto;">';
      echo '        <table class="widefat striped">';
      echo '          <thead><tr><th>משתמש</th><th>תפקידים</th>';
      foreach ($caps as $cap_label) {
        echo '        <th>' . esc_html($cap_label) . '</th>';
      }
      echo '          </tr></thead><tbody>';
      foreach ($managed_users as $user_id => $user) {
        echo '      <tr>';
        echo '        <td><strong>' . esc_html($user->display_name) . '</strong></td>';
        echo '        <td>' . esc_html(implode(', ', $user->roles)) . '</td>';
        foreach (array_keys($caps) as $cap_key) {
          $checked = !empty($data['users'][$user_id][$cap_key]);
          echo '    <td><label><input type="checkbox" name="paycal_users[' . esc_attr((string) $user_id) . '][' . esc_attr($cap_key) . ']" value="1" ' . checked($checked, true, false) . '> כן</label></td>';
        }
        echo '      </tr>';
      }
      echo '          </tbody></table>';
      echo '      </div>';
    }
    echo '    </div>';

    submit_button('שמירת הרשאות');
    echo '  </form>';
  }

  private static function maybe_handle_setup(): void {
    if ('POST' !== self::request_method()) {
      return;
    }

    if (!isset($_POST['paycal_permissions_setup_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['paycal_permissions_setup_nonce'])), 'paycal_permissions_setup')) {
      return;
    }

    $secret = isset($_POST['paycal_permissions_secret']) ? sanitize_text_field(wp_unslash($_POST['paycal_permissions_secret'])) : '';
    $confirm = isset($_POST['paycal_permissions_secret_confirm']) ? sanitize_text_field(wp_unslash($_POST['paycal_permissions_secret_confirm'])) : '';

    self::validate_secret_or_redirect($secret, $confirm);
    PermissionsStore::initialize_security_for_current_user($secret);
    self::redirect_with_notice('security_saved');
  }

  private static function maybe_handle_unlock(): void {
    if ('POST' !== self::request_method()) {
      return;
    }

    if (!isset($_POST['paycal_permissions_unlock_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['paycal_permissions_unlock_nonce'])), 'paycal_permissions_unlock')) {
      return;
    }

    $secret = isset($_POST['paycal_permissions_unlock_secret']) ? sanitize_text_field(wp_unslash($_POST['paycal_permissions_unlock_secret'])) : '';
    if (!PermissionsStore::verify_secret($secret)) {
      self::redirect_with_notice('bad_secret');
    }

    PermissionsStore::mark_current_user_verified();
    self::redirect_with_notice('unlocked');
  }

  private static function maybe_handle_lock(): void {
    if ('POST' !== self::request_method()) {
      return;
    }

    if (!isset($_POST['paycal_permissions_lock_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['paycal_permissions_lock_nonce'])), 'paycal_permissions_lock')) {
      return;
    }

    PermissionsStore::clear_current_user_verification();
    self::redirect_with_notice('locked');
  }

  private static function maybe_handle_secret_change(): void {
    if ('POST' !== self::request_method()) {
      return;
    }

    if (!isset($_POST['paycal_permissions_change_secret_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['paycal_permissions_change_secret_nonce'])), 'paycal_permissions_change_secret')) {
      return;
    }

    $secret = isset($_POST['paycal_permissions_new_secret']) ? sanitize_text_field(wp_unslash($_POST['paycal_permissions_new_secret'])) : '';
    $confirm = isset($_POST['paycal_permissions_new_secret_confirm']) ? sanitize_text_field(wp_unslash($_POST['paycal_permissions_new_secret_confirm'])) : '';

    self::validate_secret_or_redirect($secret, $confirm);
    PermissionsStore::update_secret_for_owner($secret);
    self::redirect_with_notice('secret_changed');
  }

  private static function maybe_save(): void {
    if ('POST' !== self::request_method()) {
      return;
    }

    if (!isset($_POST['paycal_permissions_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['paycal_permissions_nonce'])), 'paycal_permissions_save')) {
      return;
    }

    $roles = isset($_POST['paycal_roles']) ? map_deep(wp_unslash($_POST['paycal_roles']), 'sanitize_text_field') : [];
    $users = isset($_POST['paycal_users']) ? map_deep(wp_unslash($_POST['paycal_users']), 'sanitize_text_field') : [];

    PermissionsStore::save([
      'roles' => self::sanitize_matrix($roles),
      'users' => self::sanitize_matrix($users),
    ]);

    self::redirect_with_notice('saved');
  }

  private static function sanitize_matrix(array $data): array {
    $clean = [];
    foreach ($data as $entity_key => $caps) {
      $entity_key = is_numeric($entity_key) ? absint($entity_key) : sanitize_key($entity_key);
      foreach ((array) $caps as $cap_key => $value) {
        $clean[$entity_key][sanitize_key($cap_key)] = !empty($value);
      }
    }
    return $clean;
  }

  private static function parse_requested_users(): array {
    $requested = [];
    if (!isset($_POST['paycal_user_ids'])) {
      return $requested;
    }

    if (!isset($_POST['paycal_permissions_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['paycal_permissions_nonce'])), 'paycal_permissions_save')) {
      return $requested;
    }

    $raw = sanitize_text_field(wp_unslash($_POST['paycal_user_ids']));
    if ('' === $raw) {
      return $requested;
    }

    $ids = array_filter(array_map('absint', preg_split('/\s*,\s*/', $raw)));
    foreach ($ids as $id) {
      $user = get_userdata($id);
      if ($user) {
        $requested[] = $user;
      }
    }

    return $requested;
  }

  private static function validate_secret_or_redirect(string $secret, string $confirm): void {
    if (strlen($secret) < 6) {
      self::redirect_with_notice('secret_short');
    }

    if ($secret !== $confirm) {
      self::redirect_with_notice('secret_mismatch');
    }
  }

  private static function request_method(): string {
    return isset($_SERVER['REQUEST_METHOD']) ? strtoupper(sanitize_text_field(wp_unslash($_SERVER['REQUEST_METHOD']))) : '';
  }

  private static function redirect_with_notice(string $notice): void {
    wp_safe_redirect(add_query_arg([
      'page' => 'paycal-permissions',
      'paycal_notice' => $notice,
    ], admin_url('admin.php')));
    exit;
  }
}
