{% extends "base.html" %}

{% block title %}{{ _("devices.page_title") }}{% endblock %}

{% block content %}
<div x-data="devicesPage()" x-init="init()" class="container mx-auto px-4 py-8 max-w-6xl">

  <!-- ── Header ─────────────────────────────────────────────────────────── -->
  <header class="mb-8">
    <h1 class="text-2xl font-bold text-gray-900 dark:text-white flex items-center gap-2">
      <i class="fas fa-mobile-alt text-blue-500" aria-hidden="true"></i>
      {{ _("devices.heading") }}
    </h1>
    <p class="mt-2 text-gray-600 dark:text-gray-400 text-sm leading-relaxed max-w-2xl">
      {{ _("devices.intro") }}
    </p>
  </header>

  <!-- ── Mobile App Tokens ──────────────────────────────────────────────── -->
  <section class="bg-white dark:bg-gray-800 shadow rounded-lg overflow-hidden mb-6" aria-labelledby="mobile-tokens-heading">
    <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
      <h2 id="mobile-tokens-heading" class="text-lg font-semibold text-gray-900 dark:text-white">
        <i class="fas fa-key text-yellow-500 mr-2" aria-hidden="true"></i>{{ _("devices.mobile_tokens_heading") }}
      </h2>
      <p class="text-sm text-gray-500 dark:text-gray-400 mt-1">{{ _("devices.mobile_tokens_description") }}</p>
    </div>

    <!-- Loading -->
    <template x-if="loadingTokens">
      <div class="p-8 text-center text-gray-500 dark:text-gray-400">
        <i class="fas fa-spinner fa-spin text-2xl mb-2" aria-hidden="true"></i>
        <p class="text-sm">{{ _("devices.loading") }}</p>
      </div>
    </template>

    <!-- Empty state -->
    <template x-if="!loadingTokens && mobileTokens.length === 0">
      <div class="p-8 text-center text-gray-500 dark:text-gray-400">
        <i class="fas fa-mobile-alt text-4xl mb-3 text-gray-300 dark:text-gray-600" aria-hidden="true"></i>
        <p class="font-medium">{{ _("devices.no_mobile_tokens") }}</p>
        <p class="text-sm mt-1">{{ _("devices.no_mobile_tokens_help") }}</p>
      </div>
    </template>

    <!-- Tokens table -->
    <template x-if="!loadingTokens && mobileTokens.length > 0">
      <div class="overflow-x-auto">
        <table class="w-full text-sm" aria-label="{{ _('devices.mobile_tokens_heading') }}">
          <thead>
            <tr class="bg-gray-50 dark:bg-gray-750 text-left">
              <th scope="col" class="px-4 py-3 font-medium text-gray-500 dark:text-gray-400 uppercase text-xs tracking-wider">{{ _("devices.col_device") }}</th>
              <th scope="col" class="px-4 py-3 font-medium text-gray-500 dark:text-gray-400 uppercase text-xs tracking-wider">{{ _("devices.col_token_prefix") }}</th>
              <th scope="col" class="px-4 py-3 font-medium text-gray-500 dark:text-gray-400 uppercase text-xs tracking-wider">{{ _("devices.col_created") }}</th>
              <th scope="col" class="px-4 py-3 font-medium text-gray-500 dark:text-gray-400 uppercase text-xs tracking-wider">{{ _("devices.col_last_used") }}</th>
              <th scope="col" class="px-4 py-3 font-medium text-gray-500 dark:text-gray-400 uppercase text-xs tracking-wider">{{ _("devices.col_status") }}</th>
              <th scope="col" class="px-4 py-3 font-medium text-gray-500 dark:text-gray-400 uppercase text-xs tracking-wider sr-only">{{ _("common.actions") }}</th>
            </tr>
          </thead>
          <tbody class="divide-y divide-gray-200 dark:divide-gray-700">
            <template x-for="token in mobileTokens" :key="token.id">
              <tr class="hover:bg-gray-50 dark:hover:bg-gray-750 transition-colors">
                <td class="px-4 py-3 whitespace-nowrap">
                  <div class="flex items-center gap-2">
                    <i class="fas fa-mobile-alt text-gray-400" aria-hidden="true"></i>
                    <span class="font-medium text-gray-900 dark:text-white" x-text="formatDeviceName(token.name)"></span>
                  </div>
                </td>
                <td class="px-4 py-3 whitespace-nowrap">
                  <code class="bg-gray-100 dark:bg-gray-700 px-2 py-1 rounded text-xs font-mono" x-text="token.token_prefix + '…'"></code>
                </td>
                <td class="px-4 py-3 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400" x-text="formatDate(token.created_at)"></td>
                <td class="px-4 py-3 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
                  <span x-text="token.last_used_at ? formatDate(token.last_used_at) : '—'"></span>
                  <span x-show="token.last_used_ip" class="block text-xs text-gray-400 mt-0.5">
                    <i class="fas fa-globe mr-1" aria-hidden="true"></i><span x-text="token.last_used_ip"></span>
                  </span>
                </td>
                <td class="px-4 py-3 whitespace-nowrap">
                  <span
                    class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium"
                    :class="token.is_active ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400' : 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400'"
                    x-text="token.is_active ? '{{ _('devices.status_active') }}' : '{{ _('devices.status_revoked') }}'"
                  ></span>
                </td>
                <td class="px-4 py-3 whitespace-nowrap text-right">
                  <div class="inline-flex items-center gap-1">
                    <!-- Revoke button – shown for active tokens -->
                    <button
                      x-show="token.is_active"
                      type="button"
                      @click="revokeToken(token)"
                      :disabled="actingToken === token.id"
                      :title="'{{ _('devices.revoke_token') }}'"
                      class="inline-flex items-center justify-center w-11 h-11 text-sm text-red-600 hover:text-red-800
                             dark:text-red-400 dark:hover:text-red-300 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-md
                             focus:outline-none focus:ring-2 focus:ring-red-500 disabled:opacity-50 transition-colors"
                      :aria-label="'{{ _('devices.revoke_token') }} ' + token.name"
                    >
                      <i :class="actingToken === token.id ? 'fas fa-spinner fa-spin' : 'fas fa-sign-out-alt'" aria-hidden="true"></i>
                    </button>
                    <!-- Reactivate button – shown for revoked tokens -->
                    <button
                      x-show="!token.is_active"
                      type="button"
                      @click="reactivateMobileToken(token)"
                      :disabled="actingToken === token.id"
                      :title="'{{ _('devices.reactivate_token') }}'"
                      class="inline-flex items-center justify-center w-11 h-11 text-sm text-green-600 hover:text-green-800
                             dark:text-green-400 dark:hover:text-green-300 hover:bg-green-50 dark:hover:bg-green-900/20 rounded-md
                             focus:outline-none focus:ring-2 focus:ring-green-500 disabled:opacity-50 transition-colors"
                      :aria-label="'{{ _('devices.reactivate_token') }} ' + token.name"
                    >
                      <i :class="actingToken === token.id ? 'fas fa-spinner fa-spin' : 'fas fa-redo'" aria-hidden="true"></i>
                    </button>
                    <!-- Delete button – shown for revoked tokens -->
                    <button
                      x-show="!token.is_active"
                      type="button"
                      @click="deleteMobileToken(token)"
                      :disabled="actingToken === token.id"
                      :title="'{{ _('devices.delete_token') }}'"
                      class="inline-flex items-center justify-center w-11 h-11 text-sm text-red-600 hover:text-red-800
                             dark:text-red-400 dark:hover:text-red-300 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-md
                             focus:outline-none focus:ring-2 focus:ring-red-500 disabled:opacity-50 transition-colors"
                      :aria-label="'{{ _('devices.delete_token') }} ' + token.name"
                    >
                      <i :class="actingToken === token.id ? 'fas fa-spinner fa-spin' : 'fas fa-trash-alt'" aria-hidden="true"></i>
                    </button>
                  </div>
                </td>
              </tr>
            </template>
          </tbody>
        </table>
      </div>
    </template>

    <!-- Error -->
    <template x-if="tokenError">
      <div class="m-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 text-red-700 dark:text-red-400 p-3 rounded text-sm" role="alert">
        <i class="fas fa-exclamation-triangle mr-1" aria-hidden="true"></i>
        <span x-text="tokenError"></span>
      </div>
    </template>
  </section>

  <!-- ── Registered Devices (Push Notifications) ────────────────────────── -->
  <section class="bg-white dark:bg-gray-800 shadow rounded-lg overflow-hidden mb-6" aria-labelledby="devices-heading">
    <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700">
      <h2 id="devices-heading" class="text-lg font-semibold text-gray-900 dark:text-white">
        <i class="fas fa-bell text-purple-500 mr-2" aria-hidden="true"></i>{{ _("devices.registered_devices_heading") }}
      </h2>
      <p class="text-sm text-gray-500 dark:text-gray-400 mt-1">{{ _("devices.registered_devices_description") }}</p>
    </div>

    <!-- Loading -->
    <template x-if="loadingDevices">
      <div class="p-8 text-center text-gray-500 dark:text-gray-400">
        <i class="fas fa-spinner fa-spin text-2xl mb-2" aria-hidden="true"></i>
        <p class="text-sm">{{ _("devices.loading") }}</p>
      </div>
    </template>

    <!-- Empty state -->
    <template x-if="!loadingDevices && devices.length === 0">
      <div class="p-8 text-center text-gray-500 dark:text-gray-400">
        <i class="fas fa-bell-slash text-4xl mb-3 text-gray-300 dark:text-gray-600" aria-hidden="true"></i>
        <p class="font-medium">{{ _("devices.no_devices") }}</p>
        <p class="text-sm mt-1">{{ _("devices.no_devices_help") }}</p>
      </div>
    </template>

    <!-- Devices list -->
    <template x-if="!loadingDevices && devices.length > 0">
      <div class="divide-y divide-gray-200 dark:divide-gray-700">
        <template x-for="device in devices" :key="device.id">
          <div class="flex items-center justify-between px-6 py-4 hover:bg-gray-50 dark:hover:bg-gray-750 transition-colors">
            <div class="flex items-center gap-3 min-w-0">
              <i
                :class="device.platform === 'ios' ? 'fab fa-apple' :
                        device.platform === 'android' ? 'fab fa-android text-green-500' :
                        'fas fa-globe'"
                class="text-lg text-gray-400 flex-shrink-0"
                aria-hidden="true"
              ></i>
              <div class="min-w-0">
                <div class="text-sm font-medium text-gray-900 dark:text-white truncate">
                  <span x-text="device.device_name || 'Unknown Device'"></span>
                  <span
                    class="ml-2 inline-flex items-center px-2 py-0.5 rounded text-xs font-medium"
                    :class="device.is_active ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400' : 'bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400'"
                    x-text="device.is_active ? '{{ _('devices.status_active') }}' : '{{ _('devices.status_inactive') }}'"
                  ></span>
                </div>
                <div class="text-xs text-gray-500 dark:text-gray-400 space-x-3 mt-0.5">
                  <span>
                    <i class="fas fa-microchip mr-1" aria-hidden="true"></i>
                    <span x-text="device.platform.charAt(0).toUpperCase() + device.platform.slice(1)"></span>
                  </span>
                  <span x-show="device.last_seen_at">
                    <i class="fas fa-clock mr-1" aria-hidden="true"></i>{{ _("devices.col_last_seen") }}:
                    <span x-text="formatDate(device.last_seen_at)"></span>
                  </span>
                  <span>
                    <i class="fas fa-calendar mr-1" aria-hidden="true"></i>
                    <span x-text="formatDate(device.created_at)"></span>
                  </span>
                </div>
              </div>
            </div>
            <button
              x-show="device.is_active"
              type="button"
              @click="deactivateDevice(device)"
              :disabled="actingDevice === device.id"
              class="flex-shrink-0 inline-flex items-center px-3 py-1.5 text-sm font-medium text-red-600 hover:text-red-800
                     dark:text-red-400 dark:hover:text-red-300 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-md
                     focus:outline-none focus:ring-2 focus:ring-red-500 disabled:opacity-50 transition-colors"
              style="min-height:36px; min-width:44px;"
              :aria-label="'{{ _('devices.deactivate_device') }} ' + (device.device_name || 'device')"
            >
              <i :class="actingDevice === device.id ? 'fas fa-spinner fa-spin' : 'fas fa-power-off'" class="mr-1" aria-hidden="true"></i>
              {{ _("devices.deactivate_device") }}
            </button>
            <!-- Delete button – shown for already-inactive devices -->
            <button
              x-show="!device.is_active"
              type="button"
              @click="deleteDevice(device)"
              :disabled="actingDevice === device.id"
              class="flex-shrink-0 inline-flex items-center px-3 py-1.5 text-sm font-medium text-red-600 hover:text-red-800
                     dark:text-red-400 dark:hover:text-red-300 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-md
                     focus:outline-none focus:ring-2 focus:ring-red-500 disabled:opacity-50 transition-colors"
              style="min-height:36px; min-width:44px;"
              :aria-label="'{{ _('devices.delete_device') }} ' + (device.device_name || 'device')"
            >
              <i :class="actingDevice === device.id ? 'fas fa-spinner fa-spin' : 'fas fa-trash-alt'" class="mr-1" aria-hidden="true"></i>
              {{ _("devices.delete_device") }}
            </button>
          </div>
        </template>
      </div>
    </template>

    <!-- Error -->
    <template x-if="deviceError">
      <div class="m-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 text-red-700 dark:text-red-400 p-3 rounded text-sm" role="alert">
        <i class="fas fa-exclamation-triangle mr-1" aria-hidden="true"></i>
        <span x-text="deviceError"></span>
      </div>
    </template>
  </section>

  <!-- ── QR Login CTA ───────────────────────────────────────────────────── -->
  <div class="text-center">
    <a
      href="/qr-login"
      class="inline-flex items-center px-5 py-2.5 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium
             rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 transition-colors"
      style="min-height:44px;"
    >
      <i class="fas fa-qrcode mr-2" aria-hidden="true"></i>
      {{ _("devices.qr_login_cta") }}
    </a>
  </div>

  <!-- ── Status banner ──────────────────────────────────────────────────── -->
  <div
    x-show="banner.visible"
    x-transition
    class="mt-6 rounded-lg p-3 text-sm"
    :class="banner.error
      ? 'bg-red-50 dark:bg-red-900/30 text-red-800 dark:text-red-200 border border-red-300 dark:border-red-700'
      : 'bg-green-50 dark:bg-green-900/30 text-green-800 dark:text-green-200 border border-green-300 dark:border-green-700'"
    role="alert"
    aria-live="polite"
  >
    <span x-text="banner.message"></span>
  </div>
</div>

<script>
function devicesPage() {
  const csrfToken = '{{ csrf_token | default("") }}';
  return {
    mobileTokens: [],
    devices: [],
    loadingTokens: true,
    loadingDevices: true,
    actingToken: null,
    actingDevice: null,
    tokenError: null,
    deviceError: null,
    banner: { visible: false, error: false, message: '' },

    async init() {
      await Promise.all([this.loadMobileTokens(), this.loadDevices()]);
    },

    async loadMobileTokens() {
      this.loadingTokens = true;
      this.tokenError = null;
      try {
        const res = await fetch('/api/api-tokens/mobile', {
          headers: { 'X-CSRF-Token': csrfToken },
        });
        if (!res.ok) throw new Error('Failed to load mobile tokens');
        this.mobileTokens = await res.json();
      } catch (e) {
        this.tokenError = e.message;
      } finally {
        this.loadingTokens = false;
      }
    },

    async loadDevices() {
      this.loadingDevices = true;
      this.deviceError = null;
      try {
        const res = await fetch('/api/mobile/devices', {
          headers: { 'X-CSRF-Token': csrfToken },
        });
        if (!res.ok) throw new Error('Failed to load devices');
        this.devices = await res.json();
      } catch (e) {
        this.deviceError = e.message;
      } finally {
        this.loadingDevices = false;
      }
    },

    async revokeToken(token) {
      if (!confirm({{ _("devices.confirm_revoke_token") | tojson }})) return;
      this.actingToken = token.id;
      try {
        const res = await fetch(`/api/api-tokens/${token.id}`, {
          method: 'DELETE',
          headers: { 'X-CSRF-Token': csrfToken },
        });
        if (!res.ok) {
          const data = await res.json().catch(() => ({}));
          throw new Error(data.detail || 'Failed to revoke token');
        }
        await this.loadMobileTokens();
        this._showBanner({{ _("devices.token_revoked_success") | tojson }}, false);
      } catch (e) {
        this._showBanner(e.message, true);
      } finally {
        this.actingToken = null;
      }
    },

    async reactivateMobileToken(token) {
      if (!confirm({{ _("devices.reactivate_token_confirm") | tojson }})) return;
      this.actingToken = token.id;
      try {
        const res = await fetch(`/api/api-tokens/${token.id}/reactivate`, {
          method: 'POST',
          headers: { 'X-CSRF-Token': csrfToken },
        });
        if (!res.ok) {
          const data = await res.json().catch(() => ({}));
          throw new Error(data.detail || 'Failed to reactivate token');
        }
        await this.loadMobileTokens();
        this._showBanner({{ _("devices.token_reactivated_success") | tojson }}, false);
      } catch (e) {
        this._showBanner(e.message, true);
      } finally {
        this.actingToken = null;
      }
    },

    async deleteMobileToken(token) {
      if (!confirm({{ _("devices.delete_token_confirm") | tojson }})) return;
      this.actingToken = token.id;
      try {
        const res = await fetch(`/api/api-tokens/${token.id}`, {
          method: 'DELETE',
          headers: { 'X-CSRF-Token': csrfToken },
        });
        if (!res.ok) {
          const data = await res.json().catch(() => ({}));
          throw new Error(data.detail || 'Failed to delete token');
        }
        await this.loadMobileTokens();
        this._showBanner({{ _("devices.token_deleted_success") | tojson }}, false);
      } catch (e) {
        this._showBanner(e.message, true);
      } finally {
        this.actingToken = null;
      }
    },

    async deactivateDevice(device) {
      if (!confirm({{ _("devices.confirm_deactivate_device") | tojson }})) return;
      this.actingDevice = device.id;
      try {
        const res = await fetch(`/api/mobile/devices/${device.id}`, {
          method: 'DELETE',
          headers: { 'X-CSRF-Token': csrfToken },
        });
        if (!res.ok) {
          const data = await res.json().catch(() => ({}));
          throw new Error(data.detail || 'Failed to remove device');
        }
        await this.loadDevices();
        this._showBanner({{ _("devices.device_removed_success") | tojson }}, false);
      } catch (e) {
        this._showBanner(e.message, true);
      } finally {
        this.actingDevice = null;
      }
    },

    async deleteDevice(device) {
      if (!confirm({{ _("devices.delete_device_confirm") | tojson }})) return;
      this.actingDevice = device.id;
      try {
        const res = await fetch(`/api/mobile/devices/${device.id}`, {
          method: 'DELETE',
          headers: { 'X-CSRF-Token': csrfToken },
        });
        if (!res.ok) {
          const data = await res.json().catch(() => ({}));
          throw new Error(data.detail || 'Failed to delete device');
        }
        await this.loadDevices();
        this._showBanner({{ _("devices.device_deleted_success") | tojson }}, false);
      } catch (e) {
        this._showBanner(e.message, true);
      } finally {
        this.actingDevice = null;
      }
    },

    /** Extract the device name from the full token name (e.g. "Mobile App – iPhone 15 Pro" → "iPhone 15 Pro"). */
    formatDeviceName(name) {
      if (!name) return 'Unknown Device';
      // Match either em dash (–) or hyphen (-) separators used by the mobile flows.
      const match = name.match(/[–\-]\s*(.+)$/);
      return match ? match[1].trim() : name;
    },

    formatDate(d) {
      if (!d) return '—';
      const dt = new Date(d);
      return dt.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' }) +
        ' ' + dt.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
    },

    _showBanner(msg, isError) {
      this.banner = { visible: true, error: isError, message: msg };
      setTimeout(() => { this.banner.visible = false; }, 5000);
    },
  };
}
</script>
{% endblock %}
