{% extends "base.html" %}
{% block title %}Email Ingestion (IMAP) – DocuElevate{% endblock %}

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

  <!-- ── 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 dark:text-white flex items-center gap-2">
        <i class="fas fa-envelope-open-text text-blue-500" aria-hidden="true"></i>
        Email Ingestion (IMAP)
      </h1>
      <p class="text-gray-500 dark:text-gray-400 text-sm mt-1">
        Configure IMAP mailboxes to automatically ingest document attachments.
        DocuElevate polls each active account at regular intervals.
      </p>
    </div>
    <button
      type="button"
      @click="openCreateModal()"
      :disabled="!canAdd"
      class="inline-flex items-center px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-300 disabled:cursor-not-allowed text-white text-sm font-medium rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
      style="min-height:44px;"
      :aria-disabled="!canAdd"
    >
      <i class="fas fa-plus mr-2" aria-hidden="true"></i> Add Account
    </button>
  </div>

  <!-- ── Quota banner ─────────────────────────────────────────────────────── -->
  <div class="mb-6">
    <template x-if="quota.max_mailboxes === 0">
      <!-- Free tier: no access -->
      <div class="bg-amber-50 border border-amber-200 rounded-lg p-4 flex items-start gap-3" role="alert">
        <i class="fas fa-lock text-amber-500 mt-0.5" aria-hidden="true"></i>
        <div>
          <p class="font-semibold text-amber-800">Email ingestion not available on your plan</p>
          <p class="text-sm text-amber-700 mt-0.5">
            The <strong x-text="quota.tier_name"></strong> plan does not include IMAP ingestion.
            <a href="/subscription" class="underline hover:text-amber-900">Upgrade your plan</a>
            to unlock this feature.
          </p>
        </div>
      </div>
    </template>

    <template x-if="quota.max_mailboxes !== 0">
      <div class="bg-white dark:bg-gray-800 rounded-lg shadow px-5 py-4 flex items-center gap-4">
        <i class="fas fa-inbox text-blue-400 text-xl" aria-hidden="true"></i>
        <div class="flex-1">
          <p class="text-sm font-medium text-gray-700 dark:text-gray-200">
            IMAP accounts:
            <strong x-text="quota.current_count"></strong>
            <template x-if="quota.max_mailboxes !== null">
              <span> / <strong x-text="quota.max_mailboxes"></strong></span>
            </template>
            <template x-if="quota.max_mailboxes === null">
              <span class="text-gray-400"> / unlimited</span>
            </template>
          </p>
          <p class="text-xs text-gray-400 dark:text-gray-500 mt-0.5">
            Plan: <span x-text="quota.tier_name"></span>
            <a href="/subscription" class="ml-2 underline hover:text-blue-600">Manage subscription</a>
          </p>
        </div>
        <!-- Mini usage bar (only when a limit exists) -->
        <template x-if="quota.max_mailboxes !== null && quota.max_mailboxes > 0">
          <div class="w-32">
            <div class="bg-gray-200 dark:bg-gray-600 rounded-full h-2 overflow-hidden">
              <div
                class="h-2 rounded-full transition-all"
                :class="quota.current_count >= quota.max_mailboxes ? 'bg-red-500' : 'bg-blue-500'"
                :style="`width:${Math.min(100, quota.current_count / quota.max_mailboxes * 100)}%`"
                role="progressbar"
                :aria-valuenow="quota.current_count"
                :aria-valuemin="0"
                :aria-valuemax="quota.max_mailboxes"
                :aria-label="`${quota.current_count} of ${quota.max_mailboxes} IMAP accounts used`"
              ></div>
            </div>
          </div>
        </template>
      </div>
    </template>
  </div>

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

  <!-- ── Loading ──────────────────────────────────────────────────────────── -->
  <template x-if="loading">
    <div class="text-center py-12 text-gray-400">
      <i class="fas fa-spinner fa-spin text-3xl mb-3" aria-hidden="true"></i>
      <p>Loading accounts…</p>
    </div>
  </template>

  <!-- ── Empty state ──────────────────────────────────────────────────────── -->
  <template x-if="!loading && accounts.length === 0 && quota.max_mailboxes !== 0">
    <div class="text-center py-16 bg-white dark:bg-gray-800 rounded-lg shadow">
      <i class="fas fa-envelope-open-text text-5xl text-gray-300 mb-4" aria-hidden="true"></i>
      <h2 class="text-xl font-semibold text-gray-700 dark:text-gray-300 mb-2">No IMAP accounts yet</h2>
      <p class="text-gray-500 dark:text-gray-400 mb-6">
        Add an IMAP account and DocuElevate will automatically pull document attachments from that mailbox.
      </p>
      <button
        type="button"
        @click="openCreateModal()"
        class="inline-flex items-center px-5 py-2.5 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-md"
        style="min-height:44px;"
      >
        <i class="fas fa-plus mr-2" aria-hidden="true"></i> Add Your First Account
      </button>
    </div>
  </template>

  <!-- ── Account cards ────────────────────────────────────────────────────── -->
  <template x-if="!loading && accounts.length > 0">
    <div class="space-y-4">
      <template x-for="acct in accounts" :key="acct.id">
        <div class="bg-white dark:bg-gray-800 shadow rounded-lg overflow-hidden border border-gray-100 dark:border-gray-700">
          <div class="p-5 flex flex-col sm:flex-row sm:items-center gap-4">

            <!-- Icon + info -->
            <div class="flex items-start gap-3 flex-1 min-w-0">
              <div class="mt-0.5">
                <i
                  class="fas fa-circle text-xs"
                  :class="acct.is_active ? 'text-green-500' : 'text-gray-300'"
                  :title="acct.is_active ? 'Active' : 'Paused'"
                  aria-hidden="true"
                ></i>
              </div>
              <div class="min-w-0 flex-1">
                <h2 class="text-base font-semibold text-gray-900 dark:text-white truncate" x-text="acct.name"></h2>
                <p class="text-sm text-gray-500 dark:text-gray-400 truncate">
                  <span x-text="acct.username"></span>@<span x-text="acct.host"></span>:<span x-text="acct.port"></span>
                  <span x-show="acct.use_ssl" class="ml-1 inline-flex items-center text-xs font-medium text-green-700 bg-green-50 px-1.5 py-0.5 rounded">
                    <i class="fas fa-lock mr-1" aria-hidden="true"></i>SSL
                  </span>
                </p>

                <!-- Status row -->
                <div class="mt-1.5 flex flex-wrap gap-2 text-xs">
                  <template x-if="!acct.is_active">
                    <span class="inline-flex items-center px-2 py-0.5 rounded bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400">
                      <i class="fas fa-pause mr-1" aria-hidden="true"></i>Paused
                    </span>
                  </template>
                  <template x-if="acct.delete_after_process">
                    <span class="inline-flex items-center px-2 py-0.5 rounded bg-orange-50 text-orange-700">
                      <i class="fas fa-trash-alt mr-1" aria-hidden="true"></i>Delete after process
                    </span>
                  </template>
                  <template x-if="acct.profile_id">
                    <span class="inline-flex items-center px-2 py-0.5 rounded bg-blue-50 text-blue-700">
                      <i class="fas fa-filter mr-1" aria-hidden="true"></i><span x-text="profileName(acct.profile_id)"></span>
                    </span>
                  </template>
                  <template x-if="acct.last_checked_at">
                    <span class="text-gray-400" :title="acct.last_checked_at">
                      <i class="fas fa-clock mr-1" aria-hidden="true"></i>Last polled: <span x-text="formatDate(acct.last_checked_at)"></span>
                    </span>
                  </template>
                  <template x-if="acct.last_error">
                    <span class="inline-flex items-center px-2 py-0.5 rounded bg-red-50 text-red-700" :title="acct.last_error">
                      <i class="fas fa-exclamation-circle mr-1" aria-hidden="true"></i>Error
                    </span>
                  </template>
                </div>

                <!-- Last error detail (collapsible) -->
                <template x-if="acct.last_error">
                  <p class="mt-2 text-xs text-red-600 bg-red-50 rounded px-2 py-1 break-words" x-text="acct.last_error"></p>
                </template>
              </div>
            </div>

            <!-- Actions -->
            <div class="flex items-center gap-2 shrink-0">
              <button
                type="button"
                @click="testSavedAccount(acct)"
                :disabled="testingId === acct.id"
                class="inline-flex items-center px-3 py-1.5 text-xs font-medium rounded border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:opacity-50"
                style="min-height:36px;"
                :aria-label="`Test connection for ${acct.name}`"
              >
                <template x-if="testingId === acct.id">
                  <i class="fas fa-spinner fa-spin mr-1" aria-hidden="true"></i>
                </template>
                <template x-if="testingId !== acct.id">
                  <i class="fas fa-plug mr-1" aria-hidden="true"></i>
                </template>
                Test
              </button>
              <button
                type="button"
                @click="openEditModal(acct)"
                class="inline-flex items-center px-3 py-1.5 text-xs font-medium rounded border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
                style="min-height:36px;"
                :aria-label="`Edit ${acct.name}`"
              >
                <i class="fas fa-edit mr-1" aria-hidden="true"></i>Edit
              </button>
              <button
                type="button"
                @click="confirmDelete(acct)"
                class="inline-flex items-center px-3 py-1.5 text-xs font-medium rounded border border-red-200 text-red-600 hover:bg-red-50 focus:outline-none focus:ring-2 focus:ring-red-500"
                style="min-height:36px;"
                :aria-label="`Delete ${acct.name}`"
              >
                <i class="fas fa-trash-alt mr-1" aria-hidden="true"></i>Delete
              </button>
            </div>
          </div>
        </div>
      </template>
    </div>
  </template>

<!-- ── Create / Edit modal ──────────────────────────────────────────────────── -->
<div
  x-show="modalOpen"
  x-transition:enter="ease-out duration-200"
  x-transition:enter-start="opacity-0"
  x-transition:enter-end="opacity-100"
  x-transition:leave="ease-in duration-150"
  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/50 px-4"
  role="dialog"
  aria-modal="true"
  :aria-labelledby="editingAccount ? 'modal-title-edit' : 'modal-title-create'"
  @keydown.escape.window="closeModal()"
  style="display:none;"
>
  <div
    class="bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-lg overflow-y-auto max-h-[90vh]"
    @click.stop
  >
    <div class="px-6 pt-6 pb-2 flex items-center justify-between">
      <h2
        :id="editingAccount ? 'modal-title-edit' : 'modal-title-create'"
        class="text-lg font-semibold text-gray-900 dark:text-white"
        x-text="editingAccount ? 'Edit IMAP Account' : 'Add IMAP Account'"
      ></h2>
      <button
        type="button"
        @click="closeModal()"
        class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 rounded"
        aria-label="Close modal"
      >
        <i class="fas fa-times text-xl" aria-hidden="true"></i>
      </button>
    </div>

    <form @submit.prevent="saveAccount()" class="px-6 pb-6 pt-4 space-y-4">

      <!-- Name -->
      <div>
        <label for="acct-name" class="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
          Label <span class="text-red-500" aria-hidden="true">*</span>
        </label>
        <input
          id="acct-name"
          type="text"
          x-model="form.name"
          placeholder="e.g. Work Gmail, Scanner inbox"
          required
          maxlength="255"
          class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white text-sm"
          aria-required="true"
        />
      </div>

      <!-- Host + Port -->
      <div class="grid grid-cols-3 gap-3">
        <div class="col-span-2">
          <label for="acct-host" class="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
            IMAP Host <span class="text-red-500" aria-hidden="true">*</span>
          </label>
          <input
            id="acct-host"
            type="text"
            x-model="form.host"
            placeholder="imap.example.com"
            required
            maxlength="255"
            class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white text-sm"
            aria-required="true"
          />
        </div>
        <div>
          <label for="acct-port" class="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
            Port <span class="text-red-500" aria-hidden="true">*</span>
          </label>
          <input
            id="acct-port"
            type="number"
            x-model.number="form.port"
            min="1"
            max="65535"
            required
            class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white text-sm"
            aria-required="true"
          />
        </div>
      </div>

      <!-- Username -->
      <div>
        <label for="acct-username" class="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
          Username / Email <span class="text-red-500" aria-hidden="true">*</span>
        </label>
        <input
          id="acct-username"
          type="text"
          x-model="form.username"
          placeholder="you@example.com"
          required
          maxlength="255"
          class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white text-sm"
          aria-required="true"
          autocomplete="username"
        />
      </div>

      <!-- Password -->
      <div>
        <label for="acct-password" class="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
          Password
          <span x-show="editingAccount" class="text-xs text-gray-400 font-normal">(leave blank to keep current)</span>
          <span x-show="!editingAccount" class="text-red-500" aria-hidden="true">*</span>
        </label>
        <div class="relative">
          <input
            id="acct-password"
            :type="showPassword ? 'text' : 'password'"
            x-model="form.password"
            :required="!editingAccount"
            maxlength="1024"
            class="w-full px-3 py-2 pr-10 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white text-sm"
            :aria-required="!editingAccount"
            autocomplete="current-password"
          />
          <button
            type="button"
            @click="showPassword = !showPassword"
            class="absolute inset-y-0 right-0 px-3 text-gray-400 hover:text-gray-600 focus:outline-none"
            :aria-label="showPassword ? 'Hide password' : 'Show password'"
          >
            <i :class="showPassword ? 'fas fa-eye-slash' : 'fas fa-eye'" aria-hidden="true"></i>
          </button>
        </div>
      </div>

      <!-- SSL + Delete toggles -->
      <div class="flex flex-col sm:flex-row gap-4">
        <label class="flex items-center gap-2 cursor-pointer select-none">
          <input type="checkbox" x-model="form.use_ssl" class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500" />
          <span class="text-sm text-gray-700 dark:text-gray-200">Use SSL/TLS</span>
        </label>
        <label class="flex items-center gap-2 cursor-pointer select-none">
          <input type="checkbox" x-model="form.delete_after_process" class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500" />
          <span class="text-sm text-gray-700 dark:text-gray-200">Delete emails after processing</span>
        </label>
        <label class="flex items-center gap-2 cursor-pointer select-none">
          <input type="checkbox" x-model="form.is_active" class="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500" />
          <span class="text-sm text-gray-700 dark:text-gray-200">Active (poll this mailbox)</span>
        </label>
      </div>

      <!-- Attachment filter -->
      <div>
        <label for="acct-profile" class="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
          Ingestion Profile
        </label>
        <div class="flex gap-2 items-center">
          <select
            id="acct-profile"
            x-model.number="form.profile_id"
            class="flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white text-sm"
            aria-describedby="acct-profile-hint"
          >
            <option :value="null">Use global default</option>
            <template x-for="profile in profiles" :key="profile.id">
              <option :value="profile.id" x-text="profile.name + (profile.is_builtin ? '' : ' (custom)')"></option>
            </template>
          </select>
          <button
            type="button"
            @click="openProfileModal(null)"
            class="inline-flex items-center px-3 py-2 text-sm font-medium rounded border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
            style="min-height:40px;"
            title="Create new profile"
            aria-label="Create new ingestion profile"
          >
            <i class="fas fa-plus" aria-hidden="true"></i>
          </button>
        </div>
        <p id="acct-profile-hint" class="mt-1 text-xs text-gray-400 dark:text-gray-500">
          Controls which attachment types are ingested. Leave blank to use the global default (documents only).
          <button type="button" @click="showProfilesSection = !showProfilesSection" class="underline hover:text-blue-600 focus:outline-none">
            Manage profiles
          </button>
        </p>
        <!-- Inline selected profile summary -->
        <template x-if="form.profile_id">
          <div class="mt-2 text-xs bg-blue-50 dark:bg-blue-900/20 rounded px-2 py-1.5 text-blue-800 dark:text-blue-200">
            <strong x-text="profileName(form.profile_id)"></strong>:
            <span x-text="profileCategorySummary(form.profile_id)"></span>
          </div>
        </template>
      </div>

      <!-- Test connection result -->
      <template x-if="testResult">
        <div
          class="text-sm px-3 py-2 rounded border"
          :class="testResult.success ? 'bg-green-50 border-green-200 text-green-800' : 'bg-red-50 border-red-200 text-red-800'"
          role="status"
          aria-live="polite"
        >
          <i :class="testResult.success ? 'fas fa-check-circle' : 'fas fa-times-circle'" class="mr-1" aria-hidden="true"></i>
          <span x-text="testResult.message"></span>
        </div>
      </template>

      <!-- Form errors -->
      <template x-if="formError">
        <p class="text-sm text-red-600" role="alert" x-text="formError"></p>
      </template>

      <!-- Actions -->
      <div class="flex items-center justify-between pt-2 border-t border-gray-100 dark:border-gray-700">
        <button
          type="button"
          @click="testFromForm()"
          :disabled="testing"
          class="inline-flex items-center px-3 py-2 text-sm font-medium rounded border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:opacity-50"
          style="min-height:40px;"
        >
          <template x-if="testing">
            <i class="fas fa-spinner fa-spin mr-2" aria-hidden="true"></i>
          </template>
          <template x-if="!testing">
            <i class="fas fa-plug mr-2" aria-hidden="true"></i>
          </template>
          Test Connection
        </button>
        <div class="flex gap-2">
          <button
            type="button"
            @click="closeModal()"
            class="px-4 py-2 text-sm font-medium rounded border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
            style="min-height:40px;"
          >
            Cancel
          </button>
          <button
            type="submit"
            :disabled="saving"
            class="inline-flex items-center px-4 py-2 text-sm font-medium rounded bg-blue-600 hover:bg-blue-700 text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50"
            style="min-height:40px;"
          >
            <template x-if="saving">
              <i class="fas fa-spinner fa-spin mr-2" aria-hidden="true"></i>
            </template>
            <span x-text="editingAccount ? 'Save Changes' : 'Add Account'"></span>
          </button>
        </div>
      </div>
    </form>
  </div>
</div>

<!-- ── Delete confirmation modal ────────────────────────────────────────────── -->
<div
  x-show="deleteModalOpen"
  x-transition
  class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 px-4"
  role="dialog"
  aria-modal="true"
  aria-labelledby="delete-modal-title"
  @keydown.escape.window="deleteModalOpen = false"
  style="display:none;"
>
  <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-sm p-6" @click.stop>
    <h2 id="delete-modal-title" class="text-lg font-semibold text-gray-900 dark:text-white mb-2">
      Delete IMAP Account?
    </h2>
    <p class="text-sm text-gray-600 dark:text-gray-300 mb-4">
      Are you sure you want to delete
      <strong x-text="accountToDelete ? accountToDelete.name : ''"></strong>?
      This action cannot be undone.
    </p>
    <div class="flex justify-end gap-2">
      <button
        type="button"
        @click="deleteModalOpen = false; accountToDelete = null"
        class="px-4 py-2 text-sm font-medium rounded border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-500"
        style="min-height:40px;"
      >
        Cancel
      </button>
      <button
        type="button"
        @click="deleteAccount()"
        :disabled="deleting"
        class="inline-flex items-center px-4 py-2 text-sm font-medium rounded bg-red-600 hover:bg-red-700 text-white focus:outline-none focus:ring-2 focus:ring-red-500 disabled:opacity-50"
        style="min-height:40px;"
      >
        <template x-if="deleting">
          <i class="fas fa-spinner fa-spin mr-2" aria-hidden="true"></i>
        </template>
        Delete
      </button>
    </div>
  </div>
</div>

</div>

<!-- ── Ingestion Profiles panel ─────────────────────────────────────────────── -->
<div
  x-show="showProfilesSection"
  x-transition
  class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 px-4"
  role="dialog"
  aria-modal="true"
  aria-labelledby="profiles-panel-title"
  @keydown.escape.window="showProfilesSection = false"
  style="display:none;"
>
  <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-2xl overflow-y-auto max-h-[90vh]" @click.stop>
    <div class="px-6 pt-6 pb-2 flex items-center justify-between">
      <h2 id="profiles-panel-title" class="text-lg font-semibold text-gray-900 dark:text-white flex items-center gap-2">
        <i class="fas fa-filter text-blue-500" aria-hidden="true"></i>
        Ingestion Profiles
      </h2>
      <button
        type="button"
        @click="showProfilesSection = false"
        class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 rounded"
        aria-label="Close profiles panel"
      >
        <i class="fas fa-times text-xl" aria-hidden="true"></i>
      </button>
    </div>
    <div class="px-6 pb-6 pt-2">
      <p class="text-sm text-gray-500 dark:text-gray-400 mb-4">
        Profiles define which attachment types are ingested from emails. Assign a profile to each IMAP account for fine-grained control.
      </p>

      <!-- Profile list -->
      <div class="space-y-3 mb-4">
        <template x-for="profile in profiles" :key="profile.id">
          <div class="border border-gray-100 dark:border-gray-700 rounded-lg p-4 flex items-start gap-3">
            <div class="flex-1 min-w-0">
              <div class="flex items-center gap-2 flex-wrap">
                <span class="font-medium text-sm text-gray-900 dark:text-white" x-text="profile.name"></span>
                <template x-if="profile.is_builtin">
                  <span class="text-xs px-1.5 py-0.5 rounded bg-gray-100 dark:bg-gray-700 text-gray-500">built-in</span>
                </template>
              </div>
              <p class="text-xs text-gray-500 dark:text-gray-400 mt-0.5" x-text="profile.description || ''"></p>
              <!-- Category badges -->
              <div class="flex flex-wrap gap-1 mt-2">
                <template x-for="cat in profile.allowed_categories" :key="cat">
                  <span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300">
                    <span x-text="categoryLabel(cat)"></span>
                  </span>
                </template>
              </div>
            </div>
            <div class="flex gap-1 shrink-0">
              <button
                type="button"
                @click="openProfileModal(profile)"
                :disabled="profile.is_builtin"
                :class="profile.is_builtin ? 'opacity-40 cursor-not-allowed' : ''"
                class="p-1.5 text-gray-400 hover:text-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 rounded"
                :aria-label="`Edit profile ${profile.name}`"
                :title="profile.is_builtin ? 'Built-in profiles cannot be edited' : 'Edit profile'"
              >
                <i class="fas fa-edit text-sm" aria-hidden="true"></i>
              </button>
              <button
                type="button"
                @click="confirmDeleteProfile(profile)"
                :disabled="profile.is_builtin"
                :class="profile.is_builtin ? 'opacity-40 cursor-not-allowed' : ''"
                class="p-1.5 text-gray-400 hover:text-red-600 focus:outline-none focus:ring-2 focus:ring-red-500 rounded"
                :aria-label="`Delete profile ${profile.name}`"
                :title="profile.is_builtin ? 'Built-in profiles cannot be deleted' : 'Delete profile'"
              >
                <i class="fas fa-trash-alt text-sm" aria-hidden="true"></i>
              </button>
            </div>
          </div>
        </template>
      </div>

      <button
        type="button"
        @click="openProfileModal(null)"
        class="inline-flex items-center px-4 py-2 text-sm font-medium rounded bg-blue-600 hover:bg-blue-700 text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
        style="min-height:40px;"
      >
        <i class="fas fa-plus mr-2" aria-hidden="true"></i> New Profile
      </button>
    </div>
  </div>
</div>

<!-- ── Profile create / edit modal ────────────────────────────────────────────── -->
<div
  x-show="profileModalOpen"
  x-transition:enter="ease-out duration-200"
  x-transition:enter-start="opacity-0"
  x-transition:enter-end="opacity-100"
  x-transition:leave="ease-in duration-150"
  x-transition:leave-start="opacity-100"
  x-transition:leave-end="opacity-0"
  class="fixed inset-0 z-[60] flex items-center justify-center bg-black/50 px-4"
  role="dialog"
  aria-modal="true"
  :aria-labelledby="editingProfile ? 'profile-modal-title-edit' : 'profile-modal-title-create'"
  @keydown.escape.window="closeProfileModal()"
  style="display:none;"
>
  <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-lg overflow-y-auto max-h-[90vh]" @click.stop>
    <div class="px-6 pt-6 pb-2 flex items-center justify-between">
      <h2
        :id="editingProfile ? 'profile-modal-title-edit' : 'profile-modal-title-create'"
        class="text-lg font-semibold text-gray-900 dark:text-white"
        x-text="editingProfile ? 'Edit Profile' : 'New Ingestion Profile'"
      ></h2>
      <button
        type="button"
        @click="closeProfileModal()"
        class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 rounded"
        aria-label="Close modal"
      >
        <i class="fas fa-times text-xl" aria-hidden="true"></i>
      </button>
    </div>

    <form @submit.prevent="saveProfile()" class="px-6 pb-6 pt-4 space-y-4">

      <!-- Profile name -->
      <div>
        <label for="profile-name" class="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
          Profile Name <span class="text-red-500" aria-hidden="true">*</span>
        </label>
        <input
          id="profile-name"
          type="text"
          x-model="profileForm.name"
          placeholder="e.g. Scanner Inbox, Finance Documents"
          required
          maxlength="255"
          class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white text-sm"
          aria-required="true"
        />
      </div>

      <!-- Description -->
      <div>
        <label for="profile-description" class="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
          Description
        </label>
        <input
          id="profile-description"
          type="text"
          x-model="profileForm.description"
          placeholder="Optional description"
          maxlength="500"
          class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white text-sm"
        />
      </div>

      <!-- Category checkboxes -->
      <div>
        <fieldset>
          <legend class="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-2">
            File Type Categories <span class="text-red-500" aria-hidden="true">*</span>
          </legend>
          <div class="space-y-2">
            <template x-for="cat in categories" :key="cat.key">
              <label class="flex items-start gap-3 cursor-pointer group">
                <input
                  type="checkbox"
                  :value="cat.key"
                  :checked="profileForm.allowed_categories.includes(cat.key)"
                  @change="toggleCategory(cat.key)"
                  class="mt-0.5 h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500"
                />
                <span class="flex-1">
                  <span class="text-sm font-medium text-gray-800 dark:text-gray-100" x-text="cat.label"></span>
                  <span class="block text-xs text-gray-500 dark:text-gray-400" x-text="cat.description"></span>
                </span>
              </label>
            </template>
          </div>
          <p x-show="profileForm.allowed_categories.length === 0" class="mt-2 text-xs text-red-600" role="alert">
            Select at least one category.
          </p>
        </fieldset>
      </div>

      <!-- Form error -->
      <template x-if="profileFormError">
        <p class="text-sm text-red-600" role="alert" x-text="profileFormError"></p>
      </template>

      <!-- Actions -->
      <div class="flex justify-end gap-2 pt-2 border-t border-gray-100 dark:border-gray-700">
        <button
          type="button"
          @click="closeProfileModal()"
          class="px-4 py-2 text-sm font-medium rounded border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
          style="min-height:40px;"
        >
          Cancel
        </button>
        <button
          type="submit"
          :disabled="savingProfile || profileForm.allowed_categories.length === 0"
          class="inline-flex items-center px-4 py-2 text-sm font-medium rounded bg-blue-600 hover:bg-blue-700 text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50"
          style="min-height:40px;"
        >
          <template x-if="savingProfile">
            <i class="fas fa-spinner fa-spin mr-2" aria-hidden="true"></i>
          </template>
          <span x-text="editingProfile ? 'Save Changes' : 'Create Profile'"></span>
        </button>
      </div>
    </form>
  </div>
</div>

<!-- ── Delete profile confirmation modal ────────────────────────────────────── -->
<div
  x-show="deleteProfileModalOpen"
  x-transition
  class="fixed inset-0 z-[60] flex items-center justify-center bg-black/50 px-4"
  role="dialog"
  aria-modal="true"
  aria-labelledby="delete-profile-modal-title"
  @keydown.escape.window="deleteProfileModalOpen = false"
  style="display:none;"
>
  <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-sm p-6" @click.stop>
    <h2 id="delete-profile-modal-title" class="text-lg font-semibold text-gray-900 dark:text-white mb-2">
      Delete Profile?
    </h2>
    <p class="text-sm text-gray-600 dark:text-gray-300 mb-4">
      Are you sure you want to delete the profile
      <strong x-text="profileToDelete ? profileToDelete.name : ''"></strong>?
      IMAP accounts using this profile will fall back to the global default.
    </p>
    <div class="flex justify-end gap-2">
      <button
        type="button"
        @click="deleteProfileModalOpen = false; profileToDelete = null"
        class="px-4 py-2 text-sm font-medium rounded border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-500"
        style="min-height:40px;"
      >
        Cancel
      </button>
      <button
        type="button"
        @click="deleteProfile()"
        :disabled="deletingProfile"
        class="inline-flex items-center px-4 py-2 text-sm font-medium rounded bg-red-600 hover:bg-red-700 text-white focus:outline-none focus:ring-2 focus:ring-red-500 disabled:opacity-50"
        style="min-height:40px;"
      >
        <template x-if="deletingProfile">
          <i class="fas fa-spinner fa-spin mr-2" aria-hidden="true"></i>
        </template>
        Delete
      </button>
    </div>
  </div>
</div>

<script>
function imapAccountsApp() {
  return {
    accounts: {{ accounts | tojson }},
    profiles: {{ profiles | tojson }},
    categories: {{ categories | tojson }},
    defaultCategories: {{ default_categories | tojson }},
    quota: {
      current_count: {{ current_count }},
      max_mailboxes: {{ max_mailboxes | tojson }},
      can_add: {{ 'true' if can_add else 'false' }},
      tier_id: {{ tier_id | tojson }},
      tier_name: {{ tier_name | tojson }},
    },
    loading: false,
    alert: { show: false, type: '', title: '', message: '' },

    // Account modal state
    modalOpen: false,
    editingAccount: null,
    form: { name: '', host: '', port: 993, username: '', password: '', use_ssl: true, delete_after_process: false, is_active: true, profile_id: null },
    showPassword: false,
    saving: false,
    testing: false,
    testResult: null,
    formError: null,

    // Account delete state
    deleteModalOpen: false,
    accountToDelete: null,
    deleting: false,

    // Test (saved account) state
    testingId: null,

    // Profiles panel & modal state
    showProfilesSection: false,
    profileModalOpen: false,
    editingProfile: null,
    profileForm: { name: '', description: '', allowed_categories: [] },
    savingProfile: false,
    profileFormError: null,
    deleteProfileModalOpen: false,
    profileToDelete: null,
    deletingProfile: false,

    get canAdd() {
      return this.quota.can_add;
    },

    init() {
      // Nothing to do — data is server-rendered
    },

    formatDate(iso) {
      if (!iso) return '';
      try {
        return new Date(iso).toLocaleString();
      } catch (e) {
        console.warn('Failed to parse date:', iso, e);
        return iso;
      }
    },

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

    // ── Profile helpers ──────────────────────────────────────────────────────

    profileById(id) {
      return this.profiles.find(p => p.id === id) || null;
    },

    profileName(id) {
      const p = this.profileById(id);
      return p ? p.name : 'Unknown profile';
    },

    profileCategorySummary(id) {
      const p = this.profileById(id);
      if (!p) return '';
      return p.allowed_categories.map(k => this.categoryLabel(k)).join(', ');
    },

    categoryLabel(key) {
      const cat = this.categories.find(c => c.key === key);
      return cat ? cat.label : key;
    },

    // ── Account modal ────────────────────────────────────────────────────────

    openCreateModal() {
      this.editingAccount = null;
      this.form = { name: '', host: '', port: 993, username: '', password: '', use_ssl: true, delete_after_process: false, is_active: true, profile_id: null };
      this.showPassword = false;
      this.testResult = null;
      this.formError = null;
      this.modalOpen = true;
    },

    openEditModal(acct) {
      this.editingAccount = acct;
      this.form = {
        name: acct.name,
        host: acct.host,
        port: acct.port,
        username: acct.username,
        password: '',  // never pre-fill password
        use_ssl: acct.use_ssl,
        delete_after_process: acct.delete_after_process,
        is_active: acct.is_active,
        profile_id: acct.profile_id || null,
      };
      this.showPassword = false;
      this.testResult = null;
      this.formError = null;
      this.modalOpen = true;
    },

    closeModal() {
      this.modalOpen = false;
      this.editingAccount = null;
      this.testResult = null;
      this.formError = null;
    },

    async saveAccount() {
      this.formError = null;
      this.saving = true;
      try {
        const payload = { ...this.form };
        // For edits: omit password if blank (backend keeps existing)
        if (this.editingAccount && payload.password === '') {
          delete payload.password;
        }
        // Normalise profile_id: empty string → null
        if (payload.profile_id === '' || payload.profile_id === 0) payload.profile_id = null;
        let resp;
        if (this.editingAccount) {
          resp = await fetch(`/api/imap-accounts/${this.editingAccount.id}`, {
            method: 'PUT',
            headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': getCsrfToken() },
            body: JSON.stringify(payload),
          });
        } else {
          resp = await fetch('/api/imap-accounts/', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': getCsrfToken() },
            body: JSON.stringify(payload),
          });
        }
        const data = await resp.json();
        if (!resp.ok) {
          this.formError = data.detail || 'Failed to save account.';
          return;
        }
        // Update local list
        if (this.editingAccount) {
          const idx = this.accounts.findIndex(a => a.id === data.id);
          if (idx !== -1) this.accounts.splice(idx, 1, data);
        } else {
          this.accounts.push(data);
          this.quota.current_count += 1;
          // Re-compute canAdd
          if (this.quota.max_mailboxes !== null && this.quota.max_mailboxes > 0) {
            this.quota.can_add = this.quota.current_count < this.quota.max_mailboxes;
          }
        }
        this.closeModal();
        this.showAlert('success', 'Saved', this.editingAccount ? 'Account updated.' : 'Account added successfully.');
      } catch (err) {
        this.formError = `Network error: ${err.message || 'Unknown error'}. Please try again.`;
      } finally {
        this.saving = false;
      }
    },

    async testFromForm() {
      this.testing = true;
      this.testResult = null;
      try {
        const payload = {
          host: this.form.host,
          port: this.form.port,
          username: this.form.username,
          password: this.form.password || (this.editingAccount ? '__SAVED__' : ''),
          use_ssl: this.form.use_ssl,
        };
        // If editing and no new password, test the saved account directly
        if (this.editingAccount && !this.form.password) {
          const resp = await fetch(`/api/imap-accounts/${this.editingAccount.id}/test`, {
            method: 'POST',
            headers: { 'X-CSRF-Token': getCsrfToken() },
          });
          const data = await resp.json();
          this.testResult = data;
          return;
        }
        const resp = await fetch('/api/imap-accounts/test', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': getCsrfToken() },
          body: JSON.stringify(payload),
        });
        const data = await resp.json();
        this.testResult = data;
      } catch (err) {
        this.testResult = { success: false, message: `Network error: ${err.message || 'Unknown error'}` };
      } finally {
        this.testing = false;
      }
    },

    async testSavedAccount(acct) {
      this.testingId = acct.id;
      try {
        const resp = await fetch(`/api/imap-accounts/${acct.id}/test`, {
          method: 'POST',
          headers: { 'X-CSRF-Token': getCsrfToken() },
        });
        const data = await resp.json();
        if (data.success) {
          this.showAlert('success', `${acct.name}: Connection OK`, data.message);
        } else {
          this.showAlert('error', `${acct.name}: Connection Failed`, data.message);
        }
      } catch (err) {
        this.showAlert('error', 'Test Failed', `Network error: ${err.message || 'Unknown error'}`);
      } finally {
        this.testingId = null;
      }
    },

    confirmDelete(acct) {
      this.accountToDelete = acct;
      this.deleteModalOpen = true;
    },

    async deleteAccount() {
      if (!this.accountToDelete) return;
      this.deleting = true;
      try {
        const resp = await fetch(`/api/imap-accounts/${this.accountToDelete.id}`, {
          method: 'DELETE',
          headers: { 'X-CSRF-Token': getCsrfToken() },
        });
        if (resp.ok || resp.status === 204) {
          this.accounts = this.accounts.filter(a => a.id !== this.accountToDelete.id);
          this.quota.current_count = Math.max(0, this.quota.current_count - 1);
          if (this.quota.max_mailboxes !== null && this.quota.max_mailboxes > 0) {
            this.quota.can_add = this.quota.current_count < this.quota.max_mailboxes;
          }
          this.showAlert('success', 'Deleted', `"${this.accountToDelete.name}" has been removed.`);
          this.deleteModalOpen = false;
          this.accountToDelete = null;
        } else {
          const data = await resp.json();
          this.showAlert('error', 'Delete Failed', data.detail || 'Could not delete account.');
        }
      } catch (err) {
        this.showAlert('error', 'Delete Failed', `Network error: ${err.message || 'Unknown error'}`);
      } finally {
        this.deleting = false;
      }
    },

    // ── Profile CRUD ─────────────────────────────────────────────────────────

    openProfileModal(profile) {
      this.editingProfile = profile;
      if (profile) {
        this.profileForm = {
          name: profile.name,
          description: profile.description || '',
          allowed_categories: [...profile.allowed_categories],
        };
      } else {
        this.profileForm = { name: '', description: '', allowed_categories: [...this.defaultCategories] };
      }
      this.profileFormError = null;
      this.profileModalOpen = true;
    },

    closeProfileModal() {
      this.profileModalOpen = false;
      this.editingProfile = null;
      this.profileFormError = null;
    },

    toggleCategory(key) {
      const idx = this.profileForm.allowed_categories.indexOf(key);
      if (idx === -1) {
        this.profileForm.allowed_categories.push(key);
      } else {
        this.profileForm.allowed_categories.splice(idx, 1);
      }
    },

    async saveProfile() {
      if (this.profileForm.allowed_categories.length === 0) {
        this.profileFormError = 'Select at least one category.';
        return;
      }
      this.profileFormError = null;
      this.savingProfile = true;
      try {
        const payload = {
          name: this.profileForm.name,
          description: this.profileForm.description || null,
          allowed_categories: this.profileForm.allowed_categories,
        };
        let resp;
        if (this.editingProfile) {
          resp = await fetch(`/api/imap-profiles/${this.editingProfile.id}`, {
            method: 'PUT',
            headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': getCsrfToken() },
            body: JSON.stringify(payload),
          });
        } else {
          resp = await fetch('/api/imap-profiles/', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': getCsrfToken() },
            body: JSON.stringify(payload),
          });
        }
        const data = await resp.json();
        if (!resp.ok) {
          this.profileFormError = data.detail || 'Failed to save profile.';
          return;
        }
        // Flatten response into the same shape used locally
        const normalized = {
          id: data.id,
          name: data.name,
          description: data.description,
          owner_id: data.owner_id,
          allowed_categories: data.allowed_categories,
          is_builtin: data.is_builtin,
        };
        if (this.editingProfile) {
          const idx = this.profiles.findIndex(p => p.id === normalized.id);
          if (idx !== -1) this.profiles.splice(idx, 1, normalized);
        } else {
          this.profiles.push(normalized);
        }
        this.closeProfileModal();
        this.showAlert('success', 'Saved', this.editingProfile ? 'Profile updated.' : 'Profile created.');
      } catch (err) {
        this.profileFormError = `Network error: ${err.message || 'Unknown error'}. Please try again.`;
      } finally {
        this.savingProfile = false;
      }
    },

    confirmDeleteProfile(profile) {
      this.profileToDelete = profile;
      this.deleteProfileModalOpen = true;
    },

    async deleteProfile() {
      if (!this.profileToDelete) return;
      this.deletingProfile = true;
      try {
        const resp = await fetch(`/api/imap-profiles/${this.profileToDelete.id}`, {
          method: 'DELETE',
          headers: { 'X-CSRF-Token': getCsrfToken() },
        });
        if (resp.ok || resp.status === 204) {
          const deletedId = this.profileToDelete.id;
          this.profiles = this.profiles.filter(p => p.id !== deletedId);
          // Clear profile_id on accounts that referenced this profile
          this.accounts.forEach(a => { if (a.profile_id === deletedId) a.profile_id = null; });
          this.showAlert('success', 'Deleted', `Profile "${this.profileToDelete.name}" removed.`);
          this.deleteProfileModalOpen = false;
          this.profileToDelete = null;
        } else {
          const data = await resp.json();
          this.showAlert('error', 'Delete Failed', data.detail || 'Could not delete profile.');
        }
      } catch (err) {
        this.showAlert('error', 'Delete Failed', `Network error: ${err.message || 'Unknown error'}`);
      } finally {
        this.deletingProfile = false;
      }
    },
  };
}

function getCsrfToken() {
  // Read CSRF token from meta tag injected by base template, or from cookie
  const meta = document.querySelector('meta[name="csrf-token"]');
  if (meta) return meta.getAttribute('content');
  return '';
}
</script>
{% endblock %}
