{% extends "base.html" %}
{% block title %}{{ _("admin_users.page_title") }}{% endblock %}

{% block content %}
<div class="container mx-auto px-4 py-8" x-data="adminUsersApp()">

  <!-- ── Header ─────────────────────────────────────────────────────────────── -->
  <div class="mb-6 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
    <div>
      <h1 class="text-3xl font-bold text-gray-900 flex items-center gap-2">
        <i class="fas fa-users text-blue-500" aria-hidden="true"></i>
        {{ _("admin_users.heading") }}
        <span class="text-xs font-semibold text-red-600 bg-red-50 border border-red-200 rounded px-2 py-0.5 ml-1">{{ _("admin_users.admin_only_badge") }}</span>
      </h1>
      <p class="text-gray-500 text-sm mt-1">
        {{ _("admin_users.subheading") }}
      </p>
    </div>
    <button
      type="button"
      @click="openCreateModal()"
      class="inline-flex items-center px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
    >
      <i class="fas fa-user-plus mr-2" aria-hidden="true"></i> {{ _("admin_users.add_user_profile_btn") }}
    </button>
    <button
      type="button"
      @click="openCreateLocalUserModal()"
      class="inline-flex items-center px-4 py-2 bg-green-600 hover:bg-green-700 text-white text-sm font-medium rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500"
    >
      <i class="fas fa-user-lock mr-2" aria-hidden="true"></i> {{ _("admin_users.create_local_account_btn") }}
    </button>
  </div>

  <!-- ── Alert banner ───────────────────────────────────────────────────────── -->
  <div x-show="alert.show" x-transition class="mb-4" role="alert" :aria-live="alert.type === 'error' ? 'assertive' : 'polite'">
    <div
      :class="alert.type === 'success'
        ? 'bg-green-50 border-green-400 text-green-800'
        : 'bg-red-50 border-red-400 text-red-800'"
      class="border-l-4 p-4 rounded"
    >
      <p class="font-semibold" x-text="alert.title"></p>
      <p class="text-sm" x-text="alert.message"></p>
    </div>
  </div>

  <!-- ── Search & pagination controls ──────────────────────────────────────── -->
  <div class="mb-4 flex flex-col sm:flex-row gap-3 items-start sm:items-center justify-between">
    <div class="flex-1 max-w-sm">
      <label for="userSearch" class="sr-only">{{ _("admin_users.search_users_label") }}</label>
      <div class="relative">
        <span class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
          <i class="fas fa-search text-gray-400 text-sm" aria-hidden="true"></i>
        </span>
        <input
          id="userSearch"
          type="search"
          x-model="search"
          @input.debounce.300ms="fetchUsers(1)"
          placeholder="{{ _('admin_users.filter_placeholder') }}"
          class="w-full pl-9 pr-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-400"
        />
      </div>
    </div>
    <div class="text-sm text-gray-500" x-text="totalLabel"></div>
  </div>

  <!-- ── Table ──────────────────────────────────────────────────────────────── -->
  <div class="bg-white shadow rounded-lg overflow-x-auto">
    <table class="min-w-full divide-y divide-gray-200" aria-label="{{ _('admin_users.heading') }}">
      <thead class="bg-gray-50">
        <tr>
          <th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{{ _("admin_users.col_user_id") }}</th>
          <th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{{ _("admin_users.col_display_name") }}</th>
          <th scope="col" class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">{{ _("admin_users.col_documents") }}</th>
          <th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{{ _("admin_users.col_last_upload") }}</th>
          <th scope="col" class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">{{ _("admin_users.col_plan") }}</th>
          <th scope="col" class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">{{ _("admin_users.col_upload_limit") }}</th>
          <th scope="col" class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">{{ _("common.status") }}</th>
          <th scope="col" class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">{{ _("common.actions") }}</th>
        </tr>
      </thead>
      <tbody class="bg-white divide-y divide-gray-200">
        <template x-if="loading">
          <tr>
            <td colspan="8" class="px-4 py-8 text-center text-gray-400">
              <i class="fas fa-spinner fa-spin mr-2" aria-hidden="true"></i> {{ _("admin_users.loading_users") }}
            </td>
          </tr>
        </template>
        <template x-if="!loading && users.length === 0">
          <tr>
            <td colspan="8" class="px-4 py-8 text-center text-gray-400">
              <i class="fas fa-users-slash text-3xl block mb-2" aria-hidden="true"></i>
              {{ _("admin_users.no_users_found") }}
              <span x-show="search"> {{ _("admin_users.no_users_search_hint") }}</span>
              <span x-show="!search"> {{ _("admin_users.no_users_add_hint") }}</span>
            </td>
          </tr>
        </template>
        <template x-for="user in users" :key="user.user_id">
          <tr class="hover:bg-gray-50">
            <!-- User ID -->
            <td class="px-4 py-3 text-sm">
              <div class="flex items-center gap-2">
                <span class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-blue-100 text-blue-700 font-semibold text-xs flex-shrink-0"
                      x-text="userInitials(user.user_id)" aria-hidden="true"></span>
                <span class="font-mono text-gray-800 text-xs truncate max-w-xs" x-text="user.user_id" :title="user.user_id"></span>
              </div>
            </td>
            <!-- Display name -->
            <td class="px-4 py-3 text-sm text-gray-700" x-text="user.display_name || '—'"></td>
            <!-- Document count -->
            <td class="px-4 py-3 text-sm text-center">
              <a
                :href="`/files?owner_id=${encodeURIComponent(user.user_id)}`"
                class="inline-flex items-center gap-1 text-blue-600 hover:underline font-medium"
                :aria-label="`View ${user.document_count} document${user.document_count !== 1 ? 's' : ''} for ${user.user_id}`"
              >
                <i class="fas fa-file text-xs" aria-hidden="true"></i>
                <span x-text="user.document_count"></span>
              </a>
            </td>
            <!-- Last upload -->
            <td class="px-4 py-3 text-sm text-gray-500 whitespace-nowrap"
                x-text="user.last_upload ? formatDate(user.last_upload) : '—'"></td>
            <!-- Subscription plan -->
            <td class="px-4 py-3 text-sm text-center">
              <span
                :class="{
                  'bg-gray-100 text-gray-600': !user.subscription_tier || user.subscription_tier === 'free',
                  'bg-blue-100 text-blue-700': user.subscription_tier === 'starter',
                  'bg-indigo-100 text-indigo-700': user.subscription_tier === 'professional',
                  'bg-purple-100 text-purple-700': user.subscription_tier === 'business',
                }"
                class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-semibold capitalize"
              >
                <i
                  :class="{
                    'fas fa-seedling': !user.subscription_tier || user.subscription_tier === 'free',
                    'fas fa-rocket': user.subscription_tier === 'starter',
                    'fas fa-star': user.subscription_tier === 'professional',
                    'fas fa-building': user.subscription_tier === 'business',
                  }"
                  aria-hidden="true"
                ></i>
                <span x-text="user.subscription_tier || 'free'"></span>
              </span>
              <span
                x-show="user.is_complimentary"
                class="ml-1 inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-semibold bg-green-100 text-green-700"
                aria-label="Complimentary plan — not billed"
              >
                <i class="fas fa-gift" aria-hidden="true"></i>
              </span>
            </td>
            <!-- Upload limit -->
            <td class="px-4 py-3 text-sm text-center text-gray-700">
              <span x-show="user.daily_upload_limit !== null && user.daily_upload_limit !== undefined"
                    class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-indigo-100 text-indigo-700"
                    x-text="user.daily_upload_limit + ' {{ _("admin_users.per_day") }}'"></span>
              <span x-show="user.daily_upload_limit === null || user.daily_upload_limit === undefined"
                    class="text-gray-400 text-xs">{{ _("admin_users.global_default") }}</span>
            </td>
            <!-- Status -->
            <td class="px-4 py-3 text-sm text-center">
              <span
                :class="user.is_blocked
                  ? 'bg-red-100 text-red-700'
                  : 'bg-green-100 text-green-700'"
                class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium"
              >
                <i :class="user.is_blocked ? 'fas fa-ban' : 'fas fa-check-circle'" aria-hidden="true"></i>
                <span x-text="user.is_blocked ? '{{ _("admin_users.status_blocked") }}' : '{{ _("common.active") }}'"></span>
              </span>
            </td>
            <!-- Actions -->
            <td class="px-4 py-3 text-sm text-right whitespace-nowrap">
              <button
                type="button"
                @click="openEditModal(user)"
                class="inline-flex items-center px-2.5 py-1.5 text-xs font-medium rounded border border-gray-300 text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-blue-500 mr-1"
                :aria-label="`{{ _('common.edit') }} ${user.user_id}`"
              >
                <i class="fas fa-edit mr-1" aria-hidden="true"></i> {{ _("common.edit") }}
              </button>
              <button
                type="button"
                @click="confirmDelete(user)"
                x-show="user.profile_id !== null"
                class="inline-flex items-center px-2.5 py-1.5 text-xs font-medium rounded border border-red-300 text-red-600 bg-white hover:bg-red-50 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-red-400"
                :aria-label="`{{ _('common.delete') }} ${user.user_id}`"
              >
                <i class="fas fa-trash mr-1" aria-hidden="true"></i> {{ _("common.delete") }}
              </button>
            </td>
          </tr>
        </template>
      </tbody>
    </table>
  </div>

  <!-- ── Pagination ─────────────────────────────────────────────────────────── -->
  <div class="mt-4 flex items-center justify-between" x-show="pages > 1">
    <button
      type="button"
      @click="fetchUsers(currentPage - 1)"
      :disabled="currentPage <= 1"
      class="px-3 py-1.5 text-sm border border-gray-300 rounded hover:bg-gray-50 disabled:opacity-40 disabled:cursor-not-allowed"
    >
      <i class="fas fa-chevron-left mr-1" aria-hidden="true"></i> {{ _("common.previous") }}
    </button>
    <span class="text-sm text-gray-500">
      {{ _("common.page") }} <span x-text="currentPage"></span> {{ _("admin_users.pagination_page_of") }} <span x-text="pages"></span>
    </span>
    <button
      type="button"
      @click="fetchUsers(currentPage + 1)"
      :disabled="currentPage >= pages"
      class="px-3 py-1.5 text-sm border border-gray-300 rounded hover:bg-gray-50 disabled:opacity-40 disabled:cursor-not-allowed"
    >
      {{ _("common.next") }} <i class="fas fa-chevron-right ml-1" aria-hidden="true"></i>
    </button>
  </div>

  <!-- ══════════════════════════════════════════════════════════════════════════
       EDIT / CREATE MODAL
       ═══════════════════════════════════════════════════════════════════════ -->
  <div
    x-show="modalOpen"
    x-transition:enter="transition ease-out duration-150"
    x-transition:enter-start="opacity-0"
    x-transition:enter-end="opacity-100"
    x-transition:leave="transition ease-in duration-100"
    x-transition:leave-start="opacity-100"
    x-transition:leave-end="opacity-0"
    class="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 px-4"
    role="dialog"
    aria-modal="true"
    :aria-labelledby="'modal-title'"
  >
    <div
      class="bg-white rounded-lg shadow-xl w-full max-w-lg"
      @click.outside="modalOpen = false"
    >
      <div class="flex items-center justify-between px-6 py-4 border-b">
        <h2 id="modal-title" class="text-lg font-semibold text-gray-900" x-text="modalTitle"></h2>
        <button
          type="button"
          @click="modalOpen = false"
          class="text-gray-400 hover:text-gray-600 focus:outline-none"
          aria-label="{{ _('admin_users.modal_close_aria') }}"
        >
          <i class="fas fa-times" aria-hidden="true"></i>
        </button>
      </div>

      <form @submit.prevent="saveProfile()">
        <div class="px-6 py-5 space-y-4">

          <!-- User ID (read-only when editing) -->
          <div>
            <label for="modal-user-id" class="block text-sm font-medium text-gray-700 mb-1">{{ _("admin_users.modal_user_id_label") }}</label>
            <input
              id="modal-user-id"
              type="text"
              x-model="form.user_id"
              :readonly="!isCreate"
              :class="!isCreate ? 'bg-gray-100 cursor-not-allowed' : ''"
              class="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-400"
              placeholder="{{ _('admin_users.modal_user_id_placeholder') }}"
              required
              aria-required="true"
              autocomplete="off"
            />
            <p class="text-xs text-gray-400 mt-1">{{ _("admin_users.modal_user_id_hint") }}</p>
          </div>

          <!-- Display name -->
          <div>
            <label for="modal-display-name" class="block text-sm font-medium text-gray-700 mb-1">{{ _("admin_users.modal_display_name_label") }}</label>
            <input
              id="modal-display-name"
              type="text"
              x-model="form.display_name"
              maxlength="255"
              class="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-400"
              placeholder="{{ _('admin_users.modal_display_name_placeholder') }}"
            />
          </div>

          <!-- Daily upload limit -->
          <div>
            <label for="modal-limit" class="block text-sm font-medium text-gray-700 mb-1">
              {{ _("admin_users.modal_daily_limit_label") }}
              <span class="ml-1 text-xs font-normal text-gray-400">{{ _("admin_users.modal_daily_limit_hint") }}</span>
            </label>
            <input
              id="modal-limit"
              type="number"
              x-model.number="form.daily_upload_limit"
              min="0"
              class="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-400"
              placeholder="{{ _('admin_users.modal_daily_limit_placeholder') }}"
            />
          </div>

          <!-- Notes -->
          <div>
            <label for="modal-notes" class="block text-sm font-medium text-gray-700 mb-1">{{ _("admin_users.modal_notes_label") }}</label>
            <textarea
              id="modal-notes"
              x-model="form.notes"
              rows="3"
              maxlength="4096"
              class="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 resize-y"
              placeholder="{{ _('admin_users.modal_notes_placeholder') }}"
            ></textarea>
          </div>

          <!-- Blocked toggle -->
          <div class="flex items-center gap-3">
            <button
              type="button"
              @click="form.is_blocked = !form.is_blocked"
              :class="form.is_blocked ? 'bg-red-500' : 'bg-gray-200'"
              class="relative inline-flex h-6 w-10 flex-shrink-0 rounded-full cursor-pointer transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-blue-400"
              role="switch"
              :aria-checked="form.is_blocked.toString()"
              aria-labelledby="modal-blocked-label"
            >
              <span
                :class="form.is_blocked ? 'translate-x-4' : 'translate-x-0'"
                class="absolute top-0.5 left-0.5 h-5 w-5 rounded-full bg-white shadow transform transition duration-200 ease-in-out pointer-events-none"
              ></span>
            </button>
            <span id="modal-blocked-label" class="text-sm font-medium text-gray-700">
              {{ _("admin_users.modal_block_label") }}
              <span class="text-xs text-gray-400 font-normal">{{ _("admin_users.modal_block_hint") }}</span>
            </span>
          </div>

          <!-- Subscription tier -->
          <div>
            <label for="modal-tier" class="block text-sm font-medium text-gray-700 mb-1">
              {{ _("admin_users.modal_plan_label") }}
            </label>
            <select
              id="modal-tier"
              x-model="form.subscription_tier"
              class="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 bg-white"
            >
              <option value="free">{{ _("admin_users.modal_plan_free") }}</option>
              <option value="starter">{{ _("admin_users.modal_plan_starter") }}</option>
              <option value="professional">{{ _("admin_users.modal_plan_professional") }}</option>
              <option value="business">{{ _("admin_users.modal_plan_business") }}</option>
            </select>
            <p class="text-xs text-gray-400 mt-1">
              {{ _("admin_users.modal_plan_hint") }}
            </p>
          </div>

          <!-- Billing cycle -->
          <div>
            <label for="modal-billing-cycle" class="block text-sm font-medium text-gray-700 mb-1">
              {{ _("admin_users.modal_billing_cycle_label") }}
            </label>
            <select
              id="modal-billing-cycle"
              x-model="form.subscription_billing_cycle"
              class="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 bg-white"
            >
              <option value="monthly">{{ _("admin_users.modal_billing_monthly") }}</option>
              <option value="yearly">{{ _("admin_users.modal_billing_yearly") }}</option>
            </select>
          </div>

          <!-- Subscription period start (only shown for yearly) -->
          <div x-show="form.subscription_billing_cycle === 'yearly'" x-cloak>
            <label for="modal-period-start" class="block text-sm font-medium text-gray-700 mb-1">
              {{ _("admin_users.modal_period_start_label") }}
            </label>
            <input
              type="date"
              id="modal-period-start"
              x-model="form.subscription_period_start"
              class="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-400"
            />
            <p class="text-xs text-gray-400 mt-1">
              {{ _("admin_users.modal_period_start_hint") }}
            </p>
          </div>

          <!-- Complimentary plan toggle -->
          <div class="flex items-center gap-3">
            <button
              type="button"
              @click="form.is_complimentary = !form.is_complimentary"
              :class="form.is_complimentary ? 'bg-green-500' : 'bg-gray-200'"
              class="relative inline-flex h-6 w-10 flex-shrink-0 rounded-full cursor-pointer transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-blue-400"
              role="switch"
              :aria-checked="form.is_complimentary.toString()"
              aria-labelledby="modal-complimentary-label"
            >
              <span
                :class="form.is_complimentary ? 'translate-x-4' : 'translate-x-0'"
                class="absolute top-0.5 left-0.5 h-5 w-5 rounded-full bg-white shadow transform transition duration-200 ease-in-out pointer-events-none"
              ></span>
            </button>
            <span id="modal-complimentary-label" class="text-sm font-medium text-gray-700">
              {{ _("admin_users.modal_complimentary_label") }}
              <span class="text-xs text-gray-400 font-normal">{{ _("admin_users.modal_complimentary_hint") }}</span>
            </span>
          </div>

        </div>

        <!-- Footer -->
        <div class="px-6 py-4 border-t flex justify-end gap-3">
          <button
            type="button"
            @click="modalOpen = false"
            class="px-4 py-2 text-sm font-medium border border-gray-300 rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-gray-400"
          >
            {{ _("common.cancel") }}
          </button>
          <button
            type="submit"
            :disabled="saving"
            class="px-4 py-2 text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed"
          >
            <span x-show="!saving" x-text="isCreate ? '{{ _('common.create') }}' : '{{ _('admin_users.modal_save_changes') }}'"></span>
            <span x-show="saving"><i class="fas fa-spinner fa-spin mr-1" aria-hidden="true"></i> {{ _("admin_users.modal_saving") }}</span>
          </button>
        </div>
      </form>
    </div>
  </div>

  <!-- ── Local Accounts section ────────────────────────────────────────────── -->
  <div class="bg-white shadow rounded-lg mt-8">
    <div class="px-6 py-4 border-b flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
      <div>
        <h2 class="text-lg font-semibold text-gray-900 flex items-center gap-2">
          <i class="fas fa-user-lock text-green-600" aria-hidden="true"></i>
          {{ _("admin_users.local_accounts_heading") }}
        </h2>
        <p class="text-sm text-gray-500 mt-0.5">
          {{ _("admin_users.local_accounts_subheading") }}
        </p>
      </div>
      <button
        type="button"
        @click="openCreateLocalUserModal()"
        class="inline-flex items-center px-3 py-1.5 bg-green-600 hover:bg-green-700 text-white text-sm font-medium rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500"
      >
        <i class="fas fa-plus mr-1" aria-hidden="true"></i> {{ _("admin_users.new_account_btn") }}
      </button>
    </div>
    <div class="overflow-x-auto">
      <table class="min-w-full divide-y divide-gray-200" aria-label="{{ _('admin_users.local_accounts_heading') }}">
        <thead class="bg-gray-50">
          <tr>
            <th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{{ _("admin_users.col_username") }}</th>
            <th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{{ _("admin_users.col_email") }}</th>
            <th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{{ _("admin_users.col_display_name") }}</th>
            <th scope="col" class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">{{ _("common.status") }}</th>
            <th scope="col" class="px-4 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">{{ _("admin_users.col_role") }}</th>
            <th scope="col" class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">{{ _("common.created") }}</th>
            <th scope="col" class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">{{ _("common.actions") }}</th>
          </tr>
        </thead>
        <tbody class="bg-white divide-y divide-gray-200">
          <template x-if="localUsersLoading">
            <tr>
              <td colspan="7" class="px-4 py-6 text-center text-gray-400">
                <i class="fas fa-spinner fa-spin mr-2" aria-hidden="true"></i> {{ _("admin_users.local_loading") }}
              </td>
            </tr>
          </template>
          <template x-if="!localUsersLoading && localUsers.length === 0">
            <tr>
              <td colspan="7" class="px-4 py-6 text-center text-gray-400">
                {{ _("admin_users.local_no_accounts") }}
                <button type="button" @click="openCreateLocalUserModal()" class="text-green-600 hover:underline ml-1">{{ _("admin_users.local_create_one") }}</button>
              </td>
            </tr>
          </template>
          <template x-for="lu in localUsers" :key="lu.id">
            <tr class="hover:bg-gray-50">
              <td class="px-4 py-3 text-sm font-mono text-gray-800" x-text="lu.username"></td>
              <td class="px-4 py-3 text-sm text-gray-600" x-text="lu.email"></td>
              <td class="px-4 py-3 text-sm text-gray-600" x-text="lu.display_name || '—'"></td>
              <td class="px-4 py-3 text-sm text-center">
                <span
                  :class="lu.is_active ? 'bg-green-100 text-green-800' : 'bg-yellow-100 text-yellow-800'"
                  class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium"
                  x-text="lu.is_active ? '{{ _("common.active") }}' : '{{ _("admin_users.status_unverified") }}'"
                ></span>
              </td>
              <td class="px-4 py-3 text-sm text-center">
                <span
                  :class="lu.is_admin ? 'bg-red-100 text-red-700' : 'bg-gray-100 text-gray-600'"
                  class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium"
                  x-text="lu.is_admin ? '{{ _("admin_users.role_admin") }}' : '{{ _("admin_users.role_user") }}'"
                ></span>
              </td>
              <td class="px-4 py-3 text-sm text-gray-500 whitespace-nowrap" x-text="lu.created_at ? formatDate(lu.created_at) : '—'"></td>
              <td class="px-4 py-3 text-sm text-right">
                <button
                  type="button"
                  @click="openEditLocalUserModal(lu)"
                  class="inline-flex items-center px-2.5 py-1.5 text-xs font-medium rounded border border-gray-300 text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-blue-500 mr-1"
                  :aria-label="`{{ _('common.edit') }} ${lu.username}`"
                >
                  <i class="fas fa-edit mr-1" aria-hidden="true"></i> {{ _("common.edit") }}
                </button>
                <button
                  type="button"
                  @click="openSetPasswordModal(lu)"
                  class="inline-flex items-center px-2.5 py-1.5 text-xs font-medium rounded border border-yellow-300 text-yellow-700 bg-white hover:bg-yellow-50 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-yellow-400 mr-1"
                  :aria-label="`{{ _('admin_users.btn_password') }} ${lu.username}`"
                >
                  <i class="fas fa-key mr-1" aria-hidden="true"></i> {{ _("admin_users.btn_password") }}
                </button>
                <button
                  type="button"
                  @click="sendPasswordReset(lu)"
                  class="inline-flex items-center px-2.5 py-1.5 text-xs font-medium rounded border border-indigo-300 text-indigo-600 bg-white hover:bg-indigo-50 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-indigo-400 mr-1"
                  :aria-label="`{{ _('admin_users.btn_reset') }} ${lu.username}`"
                  title="{{ _('admin_users.btn_reset') }}"
                >
                  <i class="fas fa-envelope mr-1" aria-hidden="true"></i> {{ _("admin_users.btn_reset") }}
                </button>
                <button
                  type="button"
                  @click="confirmDeleteLocalUser(lu)"
                  class="inline-flex items-center px-2.5 py-1.5 text-xs font-medium rounded border border-red-300 text-red-600 bg-white hover:bg-red-50 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-red-400"
                  :aria-label="`{{ _('common.delete') }} ${lu.username}`"
                >
                  <i class="fas fa-trash mr-1" aria-hidden="true"></i> {{ _("common.delete") }}
                </button>
              </td>
            </tr>
          </template>
        </tbody>
      </table>
    </div>
  </div>

  <!-- ── Create local user modal ────────────────────────────────────────────── -->
  <div
    x-show="localUserModal.open"
    x-transition:enter="transition ease-out duration-100"
    x-transition:enter-start="opacity-0"
    x-transition:enter-end="opacity-100"
    class="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 px-4"
    role="dialog"
    aria-modal="true"
    aria-labelledby="create-local-user-title"
  >
    <div class="bg-white rounded-lg shadow-xl w-full max-w-lg" @click.outside="localUserModal.open = false">
      <div class="px-6 py-4 border-b flex items-center justify-between">
        <h2 id="create-local-user-title" class="text-lg font-semibold text-gray-900">{{ _("admin_users.create_local_title") }}</h2>
        <button type="button" @click="localUserModal.open = false" aria-label="{{ _('common.close') }}" class="text-gray-400 hover:text-gray-600">
          <i class="fas fa-times" aria-hidden="true"></i>
        </button>
      </div>
      <form @submit.prevent="submitCreateLocalUser" class="px-6 py-5 space-y-4">
        <div>
          <label for="lu-email" class="block text-sm font-medium text-gray-700">{{ _("admin_users.col_email") }} <span aria-hidden="true" class="text-red-500">*</span></label>
          <input type="email" id="lu-email" x-model="localUserModal.form.email" required autocomplete="off"
            class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-green-500 focus:ring focus:ring-green-500 focus:ring-opacity-50 text-sm"
            style="min-height:40px;" aria-required="true">
        </div>
        <div>
          <label for="lu-username" class="block text-sm font-medium text-gray-700">{{ _("admin_users.col_username") }} <span aria-hidden="true" class="text-red-500">*</span></label>
          <input type="text" id="lu-username" x-model="localUserModal.form.username" required autocomplete="off"
            pattern="^[a-zA-Z0-9_-]+$" minlength="3" maxlength="64"
            class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-green-500 focus:ring focus:ring-green-500 focus:ring-opacity-50 text-sm"
            style="min-height:40px;" aria-required="true" aria-describedby="lu-username-hint">
          <p id="lu-username-hint" class="mt-1 text-xs text-gray-500">{{ _("admin_users.local_username_hint") }}</p>
        </div>
        <div>
          <label for="lu-display-name" class="block text-sm font-medium text-gray-700">{{ _("admin_users.col_display_name") }} <span class="text-gray-400">{{ _("admin_users.local_display_name_optional") }}</span></label>
          <input type="text" id="lu-display-name" x-model="localUserModal.form.display_name" autocomplete="off" maxlength="255"
            class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-green-500 focus:ring focus:ring-green-500 focus:ring-opacity-50 text-sm"
            style="min-height:40px;">
        </div>
        <div>
          <label for="lu-password" class="block text-sm font-medium text-gray-700">{{ _("auth.password_label") }} <span aria-hidden="true" class="text-red-500">*</span></label>
          <input type="password" id="lu-password" x-model="localUserModal.form.password" required autocomplete="new-password"
            minlength="8" maxlength="128"
            class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-green-500 focus:ring focus:ring-green-500 focus:ring-opacity-50 text-sm"
            style="min-height:40px;" aria-required="true" aria-describedby="lu-password-hint">
          <p id="lu-password-hint" class="mt-1 text-xs text-gray-500">{{ _("admin_users.local_password_hint") }}</p>
        </div>
        <div class="flex items-center gap-2">
          <input type="checkbox" id="lu-is-admin" x-model="localUserModal.form.is_admin"
            class="h-4 w-4 rounded border-gray-300 text-green-600 focus:ring-green-500">
          <label for="lu-is-admin" class="text-sm text-gray-700">{{ _("admin_users.local_admin_privileges") }}</label>
        </div>
        <div x-show="localUserModal.error" x-cloak
          class="bg-red-50 border-l-4 border-red-500 text-red-700 p-3 rounded text-sm"
          role="alert" aria-live="assertive" x-text="localUserModal.error">
        </div>
        <div class="flex justify-end gap-3 pt-2">
          <button type="button" @click="localUserModal.open = false"
            class="px-4 py-2 text-sm font-medium border border-gray-300 rounded-md text-gray-700 bg-white hover:bg-gray-50">
            {{ _("common.cancel") }}
          </button>
          <button type="submit" :disabled="localUserModal.saving"
            class="px-4 py-2 text-sm font-medium rounded-md text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-green-500 disabled:opacity-50">
            <span x-show="!localUserModal.saving">{{ _("admin_users.local_create_btn") }}</span>
            <span x-show="localUserModal.saving" x-cloak><i class="fas fa-spinner fa-spin mr-1" aria-hidden="true"></i> {{ _("admin_users.local_creating") }}</span>
          </button>
        </div>
      </form>
    </div>
  </div>

  <!-- ── Edit local user modal ────────────────────────────────────────────── -->
  <div
    x-show="editLocalUserModal.open"
    x-transition:enter="transition ease-out duration-100"
    x-transition:enter-start="opacity-0"
    x-transition:enter-end="opacity-100"
    class="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 px-4"
    role="dialog"
    aria-modal="true"
    aria-labelledby="edit-local-user-title"
  >
    <div class="bg-white rounded-lg shadow-xl w-full max-w-lg" @click.outside="editLocalUserModal.open = false">
      <div class="px-6 py-4 border-b flex items-center justify-between">
        <h2 id="edit-local-user-title" class="text-lg font-semibold text-gray-900">{{ _("admin_users.edit_local_title") }}</h2>
        <button type="button" @click="editLocalUserModal.open = false" aria-label="{{ _('common.close') }}" class="text-gray-400 hover:text-gray-600">
          <i class="fas fa-times" aria-hidden="true"></i>
        </button>
      </div>
      <form @submit.prevent="submitEditLocalUser" class="px-6 py-5 space-y-4">
        <div>
          <label for="elu-email" class="block text-sm font-medium text-gray-700">{{ _("admin_users.col_email") }} <span aria-hidden="true" class="text-red-500">*</span></label>
          <input type="email" id="elu-email" x-model="editLocalUserModal.form.email" required autocomplete="off"
            class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-500 focus:ring-opacity-50 text-sm"
            style="min-height:40px;" aria-required="true">
        </div>
        <div>
          <label for="elu-display-name" class="block text-sm font-medium text-gray-700">{{ _("admin_users.col_display_name") }} <span class="text-gray-400">{{ _("admin_users.local_display_name_optional") }}</span></label>
          <input type="text" id="elu-display-name" x-model="editLocalUserModal.form.display_name" autocomplete="off" maxlength="255"
            class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-500 focus:ring-opacity-50 text-sm"
            style="min-height:40px;">
        </div>
        <div class="flex items-center gap-2">
          <input type="checkbox" id="elu-is-admin" x-model="editLocalUserModal.form.is_admin"
            class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500">
          <label for="elu-is-admin" class="text-sm text-gray-700">{{ _("admin_users.local_admin_privileges_short") }}</label>
        </div>
        <div class="flex items-center gap-2">
          <input type="checkbox" id="elu-is-active" x-model="editLocalUserModal.form.is_active"
            class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500">
          <label for="elu-is-active" class="text-sm text-gray-700">{{ _("admin_users.local_account_active") }}</label>
        </div>
        <div x-show="editLocalUserModal.error" x-cloak
          class="bg-red-50 border-l-4 border-red-500 text-red-700 p-3 rounded text-sm"
          role="alert" aria-live="assertive" x-text="editLocalUserModal.error">
        </div>
        <div class="flex justify-end gap-3 pt-2">
          <button type="button" @click="editLocalUserModal.open = false"
            class="px-4 py-2 text-sm font-medium border border-gray-300 rounded-md text-gray-700 bg-white hover:bg-gray-50">
            {{ _("common.cancel") }}
          </button>
          <button type="submit" :disabled="editLocalUserModal.saving"
            class="px-4 py-2 text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-blue-500 disabled:opacity-50">
            <span x-show="!editLocalUserModal.saving">{{ _("admin_users.modal_save_changes") }}</span>
            <span x-show="editLocalUserModal.saving" x-cloak><i class="fas fa-spinner fa-spin mr-1" aria-hidden="true"></i> {{ _("admin_users.local_saving") }}</span>
          </button>
        </div>
      </form>
    </div>
  </div>

  <!-- ── Set password modal ────────────────────────────────────────────────── -->
  <div
    x-show="setPasswordModal.open"
    x-transition:enter="transition ease-out duration-100"
    x-transition:enter-start="opacity-0"
    x-transition:enter-end="opacity-100"
    class="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 px-4"
    role="dialog"
    aria-modal="true"
    aria-labelledby="set-password-title"
  >
    <div class="bg-white rounded-lg shadow-xl w-full max-w-md" @click.outside="setPasswordModal.open = false">
      <div class="px-6 py-4 border-b flex items-center justify-between">
        <h2 id="set-password-title" class="text-lg font-semibold text-gray-900">{{ _("admin_users.set_password_title") }}</h2>
        <button type="button" @click="setPasswordModal.open = false" aria-label="{{ _('common.close') }}" class="text-gray-400 hover:text-gray-600">
          <i class="fas fa-times" aria-hidden="true"></i>
        </button>
      </div>
      <form @submit.prevent="submitSetPassword" class="px-6 py-5 space-y-4">
        <p class="text-sm text-gray-600">
          {{ _("admin_users.set_password_desc_pre") }} <strong class="font-mono" x-text="setPasswordModal.username"></strong>.
          {{ _("admin_users.set_password_desc") }}
        </p>
        <div>
          <label for="sp-password" class="block text-sm font-medium text-gray-700">{{ _("admin_users.new_password_label") }} <span aria-hidden="true" class="text-red-500">*</span></label>
          <input type="password" id="sp-password" x-model="setPasswordModal.password" required autocomplete="new-password"
            minlength="8" maxlength="128"
            class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-yellow-500 focus:ring focus:ring-yellow-500 focus:ring-opacity-50 text-sm"
            style="min-height:40px;" aria-required="true" aria-describedby="sp-password-hint">
          <p id="sp-password-hint" class="mt-1 text-xs text-gray-500">{{ _("admin_users.local_password_hint") }}</p>
        </div>
        <div x-show="setPasswordModal.error" x-cloak
          class="bg-red-50 border-l-4 border-red-500 text-red-700 p-3 rounded text-sm"
          role="alert" aria-live="assertive" x-text="setPasswordModal.error">
        </div>
        <div class="flex justify-end gap-3 pt-2">
          <button type="button" @click="setPasswordModal.open = false"
            class="px-4 py-2 text-sm font-medium border border-gray-300 rounded-md text-gray-700 bg-white hover:bg-gray-50">
            {{ _("common.cancel") }}
          </button>
          <button type="submit" :disabled="setPasswordModal.saving"
            class="px-4 py-2 text-sm font-medium rounded-md text-white bg-yellow-600 hover:bg-yellow-700 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-yellow-500 disabled:opacity-50">
            <span x-show="!setPasswordModal.saving">{{ _("admin_users.set_password_btn") }}</span>
            <span x-show="setPasswordModal.saving" x-cloak><i class="fas fa-spinner fa-spin mr-1" aria-hidden="true"></i> {{ _("admin_users.setting") }}</span>
          </button>
        </div>
      </form>
    </div>
  </div>

  <!-- ── Delete local user confirmation modal ───────────────────────────────── -->
  <div
    x-show="deleteLocalUserModal.open"
    x-transition:enter="transition ease-out duration-100"
    x-transition:enter-start="opacity-0"
    x-transition:enter-end="opacity-100"
    class="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 px-4"
    role="dialog"
    aria-modal="true"
    aria-labelledby="delete-local-user-title"
  >
    <div class="bg-white rounded-lg shadow-xl w-full max-w-md" @click.outside="deleteLocalUserModal.open = false">
      <div class="px-6 py-4 border-b">
        <h2 id="delete-local-user-title" class="text-lg font-semibold text-gray-900">{{ _("admin_users.delete_local_title") }}</h2>
      </div>
      <div class="px-6 py-5">
        <p class="text-sm text-gray-700">
          {{ _("admin_users.delete_local_confirm") }}
          <strong class="font-mono" x-text="deleteLocalUserModal.username"></strong>
          (<span class="font-mono" x-text="deleteLocalUserModal.email"></span>)?
        </p>
        <p class="text-sm text-gray-500 mt-2">{{ _("admin_users.delete_local_warning") }}</p>
      </div>
      <div class="px-6 py-4 border-t flex justify-end gap-3">
        <button type="button" @click="deleteLocalUserModal.open = false"
          class="px-4 py-2 text-sm font-medium border border-gray-300 rounded-md text-gray-700 bg-white hover:bg-gray-50">
          {{ _("common.cancel") }}
        </button>
        <button type="button" @click="executeDeleteLocalUser()" :disabled="deleteLocalUserModal.deleting"
          class="px-4 py-2 text-sm font-medium rounded-md text-white bg-red-600 hover:bg-red-700 disabled:opacity-50">
          <span x-show="!deleteLocalUserModal.deleting">{{ _("admin_users.delete_account_btn") }}</span>
          <span x-show="deleteLocalUserModal.deleting" x-cloak><i class="fas fa-spinner fa-spin mr-1" aria-hidden="true"></i> {{ _("admin_users.deleting") }}</span>
        </button>
      </div>
    </div>
  </div>

  <!-- ── Delete confirmation modal ──────────────────────────────────────────── -->
  <div
    x-show="deleteModal.open"
    x-transition:enter="transition ease-out duration-100"
    x-transition:enter-start="opacity-0"
    x-transition:enter-end="opacity-100"
    class="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 px-4"
    role="dialog"
    aria-modal="true"
    aria-labelledby="delete-modal-title"
  >
    <div class="bg-white rounded-lg shadow-xl w-full max-w-md" @click.outside="deleteModal.open = false">
      <div class="px-6 py-4 border-b">
        <h2 id="delete-modal-title" class="text-lg font-semibold text-gray-900">{{ _("admin_users.delete_profile_title") }}</h2>
      </div>
      <div class="px-6 py-5">
        <p class="text-sm text-gray-700">
          {{ _("admin_users.delete_profile_confirm") }}
          <strong class="font-mono" x-text="deleteModal.user_id"></strong>?
        </p>
        <p class="text-sm text-gray-500 mt-2">
          {{ _("admin_users.delete_profile_warning") }}
        </p>
      </div>
      <div class="px-6 py-4 border-t flex justify-end gap-3">
        <button
          type="button"
          @click="deleteModal.open = false"
          class="px-4 py-2 text-sm font-medium border border-gray-300 rounded-md text-gray-700 bg-white hover:bg-gray-50"
        >
          {{ _("common.cancel") }}
        </button>
        <button
          type="button"
          @click="executeDelete()"
          :disabled="deleteModal.deleting"
          class="px-4 py-2 text-sm font-medium rounded-md text-white bg-red-600 hover:bg-red-700 disabled:opacity-50"
        >
          <span x-show="!deleteModal.deleting">{{ _("admin_users.delete_profile_btn") }}</span>
          <span x-show="deleteModal.deleting"><i class="fas fa-spinner fa-spin mr-1" aria-hidden="true"></i> {{ _("admin_users.deleting") }}</span>
        </button>
      </div>
    </div>
  </div>

</div>

<script>
  window.__i18nAdminUsers = {
    noUsers: {{ _("admin_users.total_no_users") | tojson }},
    oneUser: {{ _("admin_users.total_one_user") | tojson }},
    countUsers: {{ _("admin_users.total_count_users") | tojson }},
    modalAddTitle: {{ _("admin_users.modal_add_title") | tojson }},
    modalEditTitle: {{ _("admin_users.modal_edit_title") | tojson }},
    failedLoadUsers: {{ _("admin_users.js_failed_load_users") | tojson }},
    networkError: {{ _("admin_users.js_network_error") | tojson }},
    saveFailed: {{ _("admin_users.js_save_failed") | tojson }},
    saved: {{ _("admin_users.js_saved") | tojson }},
    profileSaved: {{ _("admin_users.js_profile_saved") | tojson }},
    deleteFailed: {{ _("admin_users.js_delete_failed") | tojson }},
    deleted: {{ _("admin_users.js_deleted") | tojson }},
    profileDeleted: {{ _("admin_users.js_profile_deleted") | tojson }},
    failedLoadLocal: {{ _("admin_users.js_failed_load_local") | tojson }},
    accountCreated: {{ _("admin_users.js_account_created") | tojson }},
    accountCreatedMsg: {{ _("admin_users.js_account_created_msg") | tojson }},
    failedCreate: {{ _("admin_users.js_failed_create") | tojson }},
    accountDeletedMsg: {{ _("admin_users.js_account_deleted_msg") | tojson }},
    updated: {{ _("admin_users.js_updated") | tojson }},
    accountUpdated: {{ _("admin_users.js_account_updated") | tojson }},
    failedUpdate: {{ _("admin_users.js_failed_update") | tojson }},
    passwordSet: {{ _("admin_users.js_password_set") | tojson }},
    passwordSetMsg: {{ _("admin_users.js_password_set_msg") | tojson }},
    failedSetPassword: {{ _("admin_users.js_failed_set_password") | tojson }},
    emailSent: {{ _("admin_users.js_email_sent") | tojson }},
    emailSentMsg: {{ _("admin_users.js_email_sent_msg") | tojson }},
    emailNotSent: {{ _("admin_users.js_email_not_sent") | tojson }},
    smtpNotConfigured: {{ _("admin_users.js_smtp_not_configured") | tojson }},
    failed: {{ _("admin_users.js_failed") | tojson }},
  };
</script>

<script>
function adminUsersApp() {
  const i18n = window.__i18nAdminUsers;
  return {
    // State
    users: [],
    loading: true,
    search: '',
    currentPage: 1,
    perPage: 25,
    total: 0,
    pages: 1,

    // Edit / create modal
    modalOpen: false,
    modalTitle: '',
    isCreate: false,
    saving: false,
    form: {
      user_id: '',
      display_name: '',
      daily_upload_limit: null,
      notes: '',
      is_blocked: false,
      subscription_tier: 'free',
      subscription_billing_cycle: 'monthly',
      subscription_period_start: null,
      is_complimentary: false,
    },

    // Delete modal
    deleteModal: {
      open: false,
      user_id: '',
      deleting: false,
    },

    // Local users
    localUsers: [],
    localUsersLoading: true,
    localUserModal: {
      open: false,
      saving: false,
      error: '',
      form: { email: '', username: '', display_name: '', password: '', is_admin: false },
    },
    editLocalUserModal: {
      open: false,
      id: null,
      saving: false,
      error: '',
      form: { email: '', display_name: '', is_admin: false, is_active: true },
    },
    setPasswordModal: {
      open: false,
      id: null,
      username: '',
      saving: false,
      error: '',
      password: '',
    },
    deleteLocalUserModal: {
      open: false,
      id: null,
      username: '',
      email: '',
      deleting: false,
    },

    // Alert
    alert: { show: false, type: 'success', title: '', message: '' },

    get totalLabel() {
      if (this.loading) return '';
      if (this.total === 0) return i18n.noUsers;
      if (this.total === 1) return i18n.oneUser;
      return i18n.countUsers.replace('{count}', this.total);
    },

    async init() {
      await Promise.all([this.fetchUsers(1), this.fetchLocalUsers()]);
    },

    async fetchUsers(page) {
      this.loading = true;
      this.currentPage = page;
      try {
        const params = new URLSearchParams({
          page: page,
          per_page: this.perPage,
        });
        if (this.search.trim()) params.set('q', this.search.trim());

        const resp = await fetch(`/api/admin/users/?${params}`);
        if (!resp.ok) {
          const err = await resp.json().catch(() => ({}));
          this.showAlert('error', i18n.failedLoadUsers, err.detail || resp.statusText);
          return;
        }
        const data = await resp.json();
        this.users = data.users;
        this.total = data.total;
        this.pages = data.pages;
      } catch (e) {
        this.showAlert('error', i18n.networkError, e.message);
      } finally {
        this.loading = false;
      }
    },

    openCreateModal() {
      this.isCreate = true;
      this.modalTitle = i18n.modalAddTitle;
      this.form = { user_id: '', display_name: '', daily_upload_limit: null, notes: '', is_blocked: false, subscription_tier: 'free', subscription_billing_cycle: 'monthly', subscription_period_start: null, is_complimentary: false };
      this.modalOpen = true;
    },

    openEditModal(user) {
      this.isCreate = false;
      this.modalTitle = i18n.modalEditTitle;
      this.form = {
        user_id: user.user_id,
        display_name: user.display_name || '',
        daily_upload_limit: user.daily_upload_limit !== null && user.daily_upload_limit !== undefined
          ? user.daily_upload_limit : null,
        notes: user.notes || '',
        is_blocked: !!user.is_blocked,
        subscription_tier: user.subscription_tier || 'free',
        subscription_billing_cycle: user.subscription_billing_cycle || 'monthly',
        subscription_period_start: user.subscription_period_start ? user.subscription_period_start.substring(0, 10) : null,
        is_complimentary: !!user.is_complimentary,
      };
      this.modalOpen = true;
    },

    async saveProfile() {
      this.saving = true;
      try {
        const body = {
          display_name: this.form.display_name || null,
          daily_upload_limit: this.form.daily_upload_limit !== '' && this.form.daily_upload_limit !== null
            ? Number(this.form.daily_upload_limit) : null,
          notes: this.form.notes || null,
          is_blocked: !!this.form.is_blocked,
          subscription_tier: this.form.subscription_tier || 'free',
          is_complimentary: !!this.form.is_complimentary,
        };
        const uid = encodeURIComponent(this.form.user_id);
        const resp = await fetch(`/api/admin/users/${uid}`, {
          method: 'PUT',
          headers: {
            'Content-Type': 'application/json',
            'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]')?.content || '',
          },
          body: JSON.stringify(body),
        });
        if (!resp.ok) {
          const err = await resp.json().catch(() => ({}));
          this.showAlert('error', i18n.saveFailed, err.detail || resp.statusText);
          return;
        }
        this.modalOpen = false;
        this.showAlert('success', i18n.saved, i18n.profileSaved.replace('{id}', this.form.user_id));
        await this.fetchUsers(this.currentPage);
      } catch (e) {
        this.showAlert('error', i18n.networkError, e.message);
      } finally {
        this.saving = false;
      }
    },

    confirmDelete(user) {
      this.deleteModal.user_id = user.user_id;
      this.deleteModal.deleting = false;
      this.deleteModal.open = true;
    },

    async executeDelete() {
      this.deleteModal.deleting = true;
      try {
        const uid = encodeURIComponent(this.deleteModal.user_id);
        const resp = await fetch(`/api/admin/users/${uid}`, {
          method: 'DELETE',
          headers: {
            'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]')?.content || '',
          },
        });
        if (resp.status === 204) {
          this.deleteModal.open = false;
          this.showAlert('success', i18n.deleted, i18n.profileDeleted.replace('{id}', this.deleteModal.user_id));
          await this.fetchUsers(this.currentPage);
        } else {
          const err = await resp.json().catch(() => ({}));
          this.showAlert('error', i18n.deleteFailed, err.detail || resp.statusText);
          this.deleteModal.open = false;
        }
      } catch (e) {
        this.showAlert('error', i18n.networkError, e.message);
        this.deleteModal.open = false;
      } finally {
        this.deleteModal.deleting = false;
      }
    },

    userInitials(userId) {
      if (!userId) return '?';
      // Try to get initials from email or username
      const parts = userId.split(/[@._\s-]+/);
      return parts.slice(0, 2).map(p => p[0]?.toUpperCase() || '').join('') || userId[0].toUpperCase();
    },

    formatDate(iso) {
      if (!iso) return '—';
      try {
        return new Date(iso).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });
      } catch {
        return iso;
      }
    },

    showAlert(type, title, message) {
      this.alert = { show: true, type, title, message };
      setTimeout(() => { this.alert.show = false; }, type === 'success' ? 5000 : 10000);
    },

    async fetchLocalUsers() {
      this.localUsersLoading = true;
      try {
        const resp = await fetch('/api/admin/users/local', {
          headers: { 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]')?.content || '' },
        });
        if (!resp.ok) {
          this.showAlert('error', i18n.failedLoadLocal, resp.statusText);
          return;
        }
        this.localUsers = await resp.json();
      } catch (e) {
        this.showAlert('error', i18n.networkError, e.message);
      } finally {
        this.localUsersLoading = false;
      }
    },

    openCreateLocalUserModal() {
      this.localUserModal.form = { email: '', username: '', display_name: '', password: '', is_admin: false };
      this.localUserModal.error = '';
      this.localUserModal.saving = false;
      this.localUserModal.open = true;
    },

    async submitCreateLocalUser() {
      this.localUserModal.error = '';
      this.localUserModal.saving = true;
      try {
        const resp = await fetch('/api/admin/users/local', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]')?.content || '',
          },
          body: JSON.stringify(this.localUserModal.form),
        });
        if (resp.ok) {
          this.localUserModal.open = false;
          this.showAlert('success', i18n.accountCreated, i18n.accountCreatedMsg.replace('{username}', this.localUserModal.form.username));
          await this.fetchLocalUsers();
        } else {
          const err = await resp.json().catch(() => ({}));
          this.localUserModal.error = err.detail || i18n.failedCreate;
        }
      } catch (e) {
        this.localUserModal.error = i18n.networkError + ': ' + e.message;
      } finally {
        this.localUserModal.saving = false;
      }
    },

    confirmDeleteLocalUser(lu) {
      this.deleteLocalUserModal.id = lu.id;
      this.deleteLocalUserModal.username = lu.username;
      this.deleteLocalUserModal.email = lu.email;
      this.deleteLocalUserModal.deleting = false;
      this.deleteLocalUserModal.open = true;
    },

    openEditLocalUserModal(lu) {
      this.editLocalUserModal.id = lu.id;
      this.editLocalUserModal.form = {
        email: lu.email,
        display_name: lu.display_name || '',
        is_admin: !!lu.is_admin,
        is_active: !!lu.is_active,
      };
      this.editLocalUserModal.error = '';
      this.editLocalUserModal.saving = false;
      this.editLocalUserModal.open = true;
    },

    async submitEditLocalUser() {
      this.editLocalUserModal.error = '';
      this.editLocalUserModal.saving = true;
      try {
        const resp = await fetch(`/api/admin/users/local/${this.editLocalUserModal.id}`, {
          method: 'PATCH',
          headers: {
            'Content-Type': 'application/json',
            'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]')?.content || '',
          },
          body: JSON.stringify({
            email: this.editLocalUserModal.form.email || null,
            display_name: this.editLocalUserModal.form.display_name,
            is_admin: this.editLocalUserModal.form.is_admin,
            is_active: this.editLocalUserModal.form.is_active,
          }),
        });
        if (resp.ok) {
          this.editLocalUserModal.open = false;
          this.showAlert('success', i18n.updated, i18n.accountUpdated);
          await this.fetchLocalUsers();
        } else {
          const err = await resp.json().catch(() => ({}));
          this.editLocalUserModal.error = err.detail || i18n.failedUpdate;
        }
      } catch (e) {
        this.editLocalUserModal.error = i18n.networkError + ': ' + e.message;
      } finally {
        this.editLocalUserModal.saving = false;
      }
    },

    openSetPasswordModal(lu) {
      this.setPasswordModal.id = lu.id;
      this.setPasswordModal.username = lu.username;
      this.setPasswordModal.password = '';
      this.setPasswordModal.error = '';
      this.setPasswordModal.saving = false;
      this.setPasswordModal.open = true;
    },

    async submitSetPassword() {
      this.setPasswordModal.error = '';
      this.setPasswordModal.saving = true;
      try {
        const resp = await fetch(`/api/admin/users/local/${this.setPasswordModal.id}/set-password`, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]')?.content || '',
          },
          body: JSON.stringify({ password: this.setPasswordModal.password }),
        });
        if (resp.ok) {
          this.setPasswordModal.open = false;
          this.showAlert('success', i18n.passwordSet, i18n.passwordSetMsg.replace('{username}', this.setPasswordModal.username));
        } else {
          const err = await resp.json().catch(() => ({}));
          this.setPasswordModal.error = err.detail || i18n.failedSetPassword;
        }
      } catch (e) {
        this.setPasswordModal.error = i18n.networkError + ': ' + e.message;
      } finally {
        this.setPasswordModal.saving = false;
      }
    },

    async sendPasswordReset(lu) {
      try {
        const resp = await fetch(`/api/admin/users/local/${lu.id}/send-password-reset`, {
          method: 'POST',
          headers: {
            'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]')?.content || '',
          },
        });
        const data = await resp.json().catch(() => ({}));
        if (resp.ok && data.sent) {
          this.showAlert('success', i18n.emailSent, i18n.emailSentMsg.replace('{email}', lu.email));
        } else if (resp.ok && !data.sent) {
          this.showAlert('error', i18n.emailNotSent, data.reason || i18n.smtpNotConfigured);
        } else {
          this.showAlert('error', i18n.failed, data.detail || resp.statusText);
        }
      } catch (e) {
        this.showAlert('error', i18n.networkError, e.message);
      }
    },

    async executeDeleteLocalUser() {
      this.deleteLocalUserModal.deleting = true;
      try {
        const resp = await fetch(`/api/admin/users/local/${this.deleteLocalUserModal.id}`, {
          method: 'DELETE',
          headers: { 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]')?.content || '' },
        });
        if (resp.status === 204) {
          this.deleteLocalUserModal.open = false;
          this.showAlert('success', i18n.deleted, i18n.accountDeletedMsg.replace('{username}', this.deleteLocalUserModal.username));
          await this.fetchLocalUsers();
        } else {
          const err = await resp.json().catch(() => ({}));
          this.showAlert('error', i18n.deleteFailed, err.detail || resp.statusText);
          this.deleteLocalUserModal.open = false;
        }
      } catch (e) {
        this.showAlert('error', i18n.networkError, e.message);
        this.deleteLocalUserModal.open = false;
      } finally {
        this.deleteLocalUserModal.deleting = false;
      }
    },
  };
}
</script>
{% endblock %}
