<?php
namespace PayCal\Permissions;

defined('ABSPATH') || exit;

if (!class_exists(__NAMESPACE__ . '\\PermissionsStore')) {
  class PermissionsStore {
    const OPTION_KEY = 'paycal_permissions_matrix';
    const SECURITY_OPTION_KEY = 'paycal_permissions_security';
    const VERIFIED_UNTIL_META_KEY = 'paycal_permissions_verified_until';
    const VERIFY_WINDOW = 900;

    const CAPS = [
      'dashboard'   => 'גישה ללוח הבקרה',
      'license'     => 'גישה למסך רישיון',
      'bundles'     => 'גישה לערכות',
      'bit'         => 'גישה למסך ביט',
      'invoices'    => 'גישה למסך חשבוניות',
      'setup'       => 'גישה למסך התקנה',
      'permissions' => 'ניהול הרשאות',
    ];

    public static function get(): array {
      $saved = get_option(self::OPTION_KEY, []);
      if (!is_array($saved)) {
        $saved = [];
      }

      $defaults = ['roles' => [], 'users' => []];
      $saved = wp_parse_args($saved, $defaults);
      $saved['roles'] = is_array($saved['roles']) ? $saved['roles'] : [];
      $saved['users'] = is_array($saved['users']) ? $saved['users'] : [];
      return $saved;
    }

    public static function save(array $data): void {
      $clean = ['roles' => [], 'users' => []];
      $roles = wp_roles();
      $available_caps = array_keys(self::CAPS);

      if ($roles && !empty($roles->roles)) {
        foreach (array_keys($roles->roles) as $role_key) {
          foreach ($available_caps as $cap_key) {
            $clean['roles'][$role_key][$cap_key] = !empty($data['roles'][$role_key][$cap_key]);
          }
        }
      }

      if (!empty($data['users']) && is_array($data['users'])) {
        foreach ($data['users'] as $user_id => $caps) {
          $user_id = absint($user_id);
          if (!$user_id || !get_userdata($user_id)) {
            continue;
          }

          foreach ($available_caps as $cap_key) {
            $clean['users'][$user_id][$cap_key] = !empty($caps[$cap_key]);
          }
        }
      }

      update_option(self::OPTION_KEY, $clean, false);
    }

    public static function get_managed_users(): array {
      $data = self::get();
      $users = [];
      foreach (array_keys($data['users']) as $user_id) {
        $user = get_userdata((int) $user_id);
        if ($user) {
          $users[(int) $user_id] = $user;
        }
      }
      return $users;
    }

    public static function get_security(): array {
      $saved = get_option(self::SECURITY_OPTION_KEY, []);
      if (!is_array($saved)) {
        $saved = [];
      }
      return wp_parse_args($saved, ['owner_user_id' => 0, 'secret_hash' => '']);
    }

    public static function has_permissions_lock(): bool {
      $security = self::get_security();
      return !empty($security['owner_user_id']) && !empty($security['secret_hash']);
    }

    public static function get_owner_user_id(): int {
      $security = self::get_security();
      return absint($security['owner_user_id']);
    }

    public static function current_user_is_owner(): bool {
      $owner_user_id = self::get_owner_user_id();
      return $owner_user_id > 0 && get_current_user_id() === $owner_user_id;
    }

    public static function initialize_security_for_current_user(string $secret): void {
      $user_id = get_current_user_id();
      if (!$user_id || '' === $secret) {
        return;
      }

      update_option(self::SECURITY_OPTION_KEY, [
        'owner_user_id' => $user_id,
        'secret_hash' => wp_hash_password($secret),
      ], false);

      self::mark_current_user_verified();
    }

    public static function update_secret_for_owner(string $secret): void {
      $security = self::get_security();
      if (empty($security['owner_user_id']) || '' === $secret) {
        return;
      }

      $security['secret_hash'] = wp_hash_password($secret);
      update_option(self::SECURITY_OPTION_KEY, $security, false);
      self::mark_current_user_verified();
    }

    public static function verify_secret(string $secret): bool {
      $security = self::get_security();
      if (empty($security['secret_hash']) || '' === $secret) {
        return false;
      }

      return wp_check_password($secret, $security['secret_hash']);
    }

    public static function mark_current_user_verified(): void {
      $user_id = get_current_user_id();
      if (!$user_id) {
        return;
      }

      update_user_meta($user_id, self::VERIFIED_UNTIL_META_KEY, time() + self::VERIFY_WINDOW);
    }

    public static function clear_current_user_verification(): void {
      $user_id = get_current_user_id();
      if (!$user_id) {
        return;
      }

      delete_user_meta($user_id, self::VERIFIED_UNTIL_META_KEY);
    }

    public static function current_user_is_verified(): bool {
      $user_id = get_current_user_id();
      if (!$user_id) {
        return false;
      }

      return (int) get_user_meta($user_id, self::VERIFIED_UNTIL_META_KEY, true) >= time();
    }
  }
}

if (!class_exists(__NAMESPACE__ . '\\Access')) {
  class Access {
    public static function can(string $section): bool {
      if ('permissions' === $section) {
        return self::can_manage_permissions();
      }

      if (current_user_can('manage_options')) {
        return true;
      }

      if (!array_key_exists($section, PermissionsStore::CAPS)) {
        return false;
      }

      $data = PermissionsStore::get();
      $user_id = get_current_user_id();

      if ($user_id && !empty($data['users'][$user_id][$section])) {
        return true;
      }

      $user = wp_get_current_user();
      if (!$user || empty($user->roles)) {
        return false;
      }

      foreach ((array) $user->roles as $role_key) {
        if (!empty($data['roles'][$role_key][$section])) {
          return true;
        }
      }

      return false;
    }

    public static function any(array $sections): bool {
      foreach ($sections as $section) {
        if (self::can((string) $section)) {
          return true;
        }
      }
      return false;
    }

    public static function enforce(string $section): void {
      if (self::can($section)) {
        return;
      }

      $message = 'אין לך הרשאה לצפות במסך הזה של PayCal.';
      if ('permissions' === $section) {
        $message = 'מסך ההרשאות של PayCal זמין רק למשתמש הבעלים שהוגדר עבורו.';
      }

      wp_die(
        esc_html($message),
        esc_html__('אין הרשאה', 'klamra-paycal-for-aspaclaria'),
        ['response' => 403]
      );
    }

    public static function can_manage_permissions(): bool {
      if (!current_user_can('manage_options')) {
        return false;
      }

      $owner_user_id = PermissionsStore::get_owner_user_id();
      if ($owner_user_id > 0) {
        return get_current_user_id() === $owner_user_id;
      }

      return true;
    }
  }
}
