<template>
  <div class="p-6">
    <h2 class="mb-2 text-xl font-semibold tracking-wide text-kestrel-text [text-shadow:0_0_8px_rgba(34,201,201,0.25)]">
      Members
    </h2>
    <p
      v-if="!user"
      class="text-sm text-kestrel-muted"
    >
      Sign in to view members.
    </p>
    <p
      v-else-if="!canViewMembers"
      class="text-sm text-kestrel-muted"
    >
      You don't have access to the members list.
    </p>
    <template v-else>
      <p
        v-if="isAdmin"
        class="mb-3 text-xs text-kestrel-muted"
      >
        Only admins can change roles and manage local users. OIDC users are managed via your identity provider.
      </p>
      <div
        v-if="isAdmin"
        class="mb-3 flex justify-start"
      >
        <button
          type="button"
          class="rounded border border-kestrel-accent bg-kestrel-accent/10 px-3 py-1.5 text-sm font-medium text-kestrel-accent hover:bg-kestrel-accent-dim"
          @click="openAddUserModal"
        >
          Add user
        </button>
      </div>
      <div class="overflow-x-auto rounded border border-kestrel-border">
        <table class="w-full text-left text-sm">
          <thead>
            <tr class="border-b border-kestrel-border bg-kestrel-surface-hover">
              <th class="px-4 py-2 font-medium text-kestrel-text">
                Identifier
              </th>
              <th class="px-4 py-2 font-medium text-kestrel-text">
                Auth
              </th>
              <th class="px-4 py-2 font-medium text-kestrel-text">
                Role
              </th>
              <th
                v-if="isAdmin"
                class="px-4 py-2 font-medium text-kestrel-text"
              >
                Actions
              </th>
            </tr>
          </thead>
          <tbody>
            <tr
              v-for="u in users"
              :key="u.id"
              class="border-b border-kestrel-border"
            >
              <td class="px-4 py-2 text-kestrel-text">
                {{ u.identifier }}
              </td>
              <td class="px-4 py-2">
                <span
                  class="rounded px-1.5 py-0.5 text-xs text-kestrel-muted"
                  :class="u.auth_provider === 'oidc' ? 'bg-kestrel-surface' : ''"
                >
                  {{ u.auth_provider === 'oidc' ? 'OIDC' : 'Local' }}
                </span>
              </td>
              <td class="px-4 py-2">
                <div
                  v-if="isAdmin"
                  :ref="el => setDropdownWrapRef(u.id, el)"
                  class="relative inline-block"
                >
                  <button
                    type="button"
                    class="flex min-w-[6rem] items-center justify-between gap-2 rounded border border-kestrel-border bg-kestrel-bg px-2 py-1 text-left text-sm text-kestrel-text shadow-sm transition-colors hover:border-kestrel-accent/50 hover:bg-kestrel-surface"
                    :aria-expanded="openRoleDropdownId === u.id"
                    :aria-haspopup="true"
                    aria-label="Change role"
                    @click.stop="toggleRoleDropdown(u.id)"
                  >
                    <span>{{ roleByUserId[u.id] ?? u.role }}</span>
                    <span
                      class="text-kestrel-muted transition-transform"
                      :class="openRoleDropdownId === u.id && 'rotate-180'"
                    >
                      ▾
                    </span>
                  </button>
                </div>
                <span
                  v-else
                  class="text-kestrel-muted"
                >{{ u.role }}</span>
              </td>
              <td
                v-if="isAdmin"
                class="px-4 py-2"
              >
                <div class="flex flex-wrap items-center gap-2">
                  <button
                    v-if="roleByUserId[u.id] !== u.role"
                    type="button"
                    class="rounded border border-kestrel-accent px-2 py-1 text-xs text-kestrel-accent hover:bg-kestrel-accent-dim"
                    @click="saveRole(u.id)"
                  >
                    Save role
                  </button>
                  <template v-if="u.auth_provider !== 'oidc'">
                    <button
                      type="button"
                      class="rounded border border-kestrel-border px-2 py-1 text-xs text-kestrel-text hover:bg-kestrel-surface"
                      @click="openEditUser(u)"
                    >
                      Edit
                    </button>
                    <button
                      v-if="u.id !== user?.id"
                      type="button"
                      class="rounded border border-red-500/60 px-2 py-1 text-xs text-red-400 hover:bg-red-500/10"
                      @click="openDeleteConfirm(u)"
                    >
                      Remove
                    </button>
                  </template>
                </div>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
      <Teleport to="body">
        <Transition
          enter-active-class="transition duration-100 ease-out"
          enter-from-class="opacity-0 scale-95"
          enter-to-class="opacity-100 scale-100"
          leave-active-class="transition duration-75 ease-in"
          leave-from-class="opacity-100 scale-100"
          leave-to-class="opacity-0 scale-95"
        >
          <div
            v-if="openRoleDropdownId && dropdownPlacement"
            ref="dropdownMenuRef"
            role="menu"
            class="fixed z-[100] min-w-[6rem] rounded border border-kestrel-border bg-kestrel-surface py-1 shadow-glow [box-shadow:0_4px_12px_-2px_rgba(34,201,201,0.15)]"
            :style="{
              top: `${dropdownPlacement.top}px`,
              left: `${dropdownPlacement.left}px`,
              minWidth: `${dropdownPlacement.minWidth}px`,
            }"
          >
            <button
              v-for="role in roleOptions"
              :key="role"
              type="button"
              role="menuitem"
              class="block w-full px-3 py-1.5 text-left text-sm transition-colors"
              :class="roleByUserId[openRoleDropdownId] === role
                ? 'bg-kestrel-accent-dim text-kestrel-accent'
                : 'text-kestrel-text hover:bg-kestrel-border hover:text-kestrel-text'"
              @click.stop="selectRole(openRoleDropdownId, role)"
            >
              {{ role }}
            </button>
          </div>
        </Transition>
      </Teleport>
      <!-- Add user modal -->
      <Teleport to="body">
        <div
          v-if="addUserModalOpen"
          class="fixed inset-0 z-[200] flex items-center justify-center bg-black/50 p-4"
          role="dialog"
          aria-modal="true"
          aria-labelledby="add-user-title"
          @click.self="closeAddUserModal"
        >
          <div
            class="w-full max-w-sm rounded border border-kestrel-border bg-kestrel-surface p-4 shadow-glow"
            @click.stop
          >
            <h3
              id="add-user-title"
              class="mb-3 text-sm font-medium text-kestrel-text"
            >
              Add user
            </h3>
            <form @submit.prevent="submitAddUser">
              <div class="mb-3 flex flex-col gap-1">
                <label
                  for="add-identifier"
                  class="text-xs text-kestrel-muted"
                >Username</label>
                <input
                  id="add-identifier"
                  v-model="newUser.identifier"
                  type="text"
                  required
                  autocomplete="username"
                  class="rounded border border-kestrel-border bg-kestrel-bg px-2 py-1.5 text-sm text-kestrel-text"
                  placeholder="username"
                >
              </div>
              <div class="mb-3 flex flex-col gap-1">
                <label
                  for="add-password"
                  class="text-xs text-kestrel-muted"
                >Password</label>
                <input
                  id="add-password"
                  v-model="newUser.password"
                  type="password"
                  required
                  autocomplete="new-password"
                  class="rounded border border-kestrel-border bg-kestrel-bg px-2 py-1.5 text-sm text-kestrel-text"
                  placeholder="••••••••"
                >
              </div>
              <div class="mb-4 flex flex-col gap-1">
                <label
                  for="add-role"
                  class="text-xs text-kestrel-muted"
                >Role</label>
                <select
                  id="add-role"
                  v-model="newUser.role"
                  class="rounded border border-kestrel-border bg-kestrel-bg px-2 py-1.5 text-sm text-kestrel-text"
                >
                  <option value="member">
                    member
                  </option>
                  <option value="leader">
                    leader
                  </option>
                  <option value="admin">
                    admin
                  </option>
                </select>
              </div>
              <p
                v-if="createError"
                class="mb-2 text-xs text-red-400"
              >
                {{ createError }}
              </p>
              <div class="flex justify-end gap-2">
                <button
                  type="button"
                  class="rounded border border-kestrel-border px-3 py-1.5 text-sm text-kestrel-text hover:bg-kestrel-surface-hover"
                  @click="closeAddUserModal"
                >
                  Cancel
                </button>
                <button
                  type="submit"
                  class="rounded border border-kestrel-accent px-3 py-1.5 text-sm text-kestrel-accent hover:bg-kestrel-accent-dim"
                >
                  Add user
                </button>
              </div>
            </form>
          </div>
        </div>
      </Teleport>
      <!-- Delete user confirmation modal -->
      <Teleport to="body">
        <div
          v-if="deleteConfirmUser"
          class="fixed inset-0 z-[200] flex items-center justify-center bg-black/50 p-4"
          role="dialog"
          aria-modal="true"
          aria-labelledby="delete-user-title"
          @click.self="deleteConfirmUser = null"
        >
          <div
            class="w-full max-w-sm rounded border border-kestrel-border bg-kestrel-surface p-4 shadow-glow"
            @click.stop
          >
            <h3
              id="delete-user-title"
              class="mb-2 text-sm font-medium text-kestrel-text"
            >
              Delete user?
            </h3>
            <p class="mb-4 text-sm text-kestrel-muted">
              Are you sure you want to delete <strong class="text-kestrel-text">{{ deleteConfirmUser?.identifier }}</strong>? They will not be able to sign in again.
            </p>
            <div class="flex justify-end gap-2">
              <button
                type="button"
                class="rounded border border-kestrel-border px-3 py-1.5 text-sm text-kestrel-text hover:bg-kestrel-surface-hover"
                @click="deleteConfirmUser = null"
              >
                Cancel
              </button>
              <button
                type="button"
                class="rounded border border-red-500/60 bg-red-500/10 px-3 py-1.5 text-sm text-red-400 hover:bg-red-500/20"
                @click="confirmDeleteUser"
              >
                Delete
              </button>
            </div>
          </div>
        </div>
      </Teleport>
      <Teleport to="body">
        <div
          v-if="editUserModal"
          class="fixed inset-0 z-[200] flex items-center justify-center bg-black/50 p-4"
          @click.self="editUserModal = null"
        >
          <div
            class="w-full max-w-sm rounded border border-kestrel-border bg-kestrel-surface p-4 shadow-glow"
            role="dialog"
            aria-modal="true"
            aria-labelledby="edit-user-title"
          >
            <h3
              id="edit-user-title"
              class="mb-3 text-sm font-medium text-kestrel-text"
            >
              Edit local user
            </h3>
            <form @submit.prevent="submitEditUser">
              <div class="mb-3 flex flex-col gap-1">
                <label
                  for="edit-identifier"
                  class="text-xs text-kestrel-muted"
                >Identifier</label>
                <input
                  id="edit-identifier"
                  v-model="editForm.identifier"
                  type="text"
                  required
                  class="rounded border border-kestrel-border bg-kestrel-bg px-2 py-1.5 text-sm text-kestrel-text"
                >
              </div>
              <div class="mb-4 flex flex-col gap-1">
                <label
                  for="edit-password"
                  class="text-xs text-kestrel-muted"
                >New password (leave blank to keep)</label>
                <input
                  id="edit-password"
                  v-model="editForm.password"
                  type="password"
                  autocomplete="new-password"
                  class="rounded border border-kestrel-border bg-kestrel-bg px-2 py-1.5 text-sm text-kestrel-text"
                  placeholder="••••••••"
                >
                <p class="mt-0.5 text-xs text-kestrel-muted">
                  If you change your password, use the new one next time you sign in.
                </p>
              </div>
              <p
                v-if="editError"
                class="mb-2 text-xs text-red-400"
              >
                {{ editError }}
              </p>
              <div class="flex justify-end gap-2">
                <button
                  type="button"
                  class="rounded border border-kestrel-border px-3 py-1.5 text-sm text-kestrel-text hover:bg-kestrel-surface-hover"
                  @click="editUserModal = null"
                >
                  Cancel
                </button>
                <button
                  type="submit"
                  class="rounded border border-kestrel-accent px-3 py-1.5 text-sm text-kestrel-accent hover:bg-kestrel-accent-dim"
                >
                  Save
                </button>
              </div>
            </form>
          </div>
        </div>
      </Teleport>
    </template>
  </div>
</template>

<script setup>
const { user, isAdmin, refresh: refreshUser } = useUser()
const canViewMembers = computed(() => user.value?.role === 'admin' || user.value?.role === 'leader')

const { data: usersData, refresh: refreshUsers } = useAsyncData(
  'users',
  () => $fetch('/api/users').catch(() => []),
  { default: () => [] },
)
const users = computed(() => (Array.isArray(usersData.value) ? usersData.value : []))

const roleOptions = ['admin', 'leader', 'member']
const pendingRoleUpdates = ref({})
const roleByUserId = computed(() => {
  const base = Object.fromEntries(users.value.map(u => [u.id, u.role]))
  return { ...base, ...pendingRoleUpdates.value }
})
const openRoleDropdownId = ref(null)
const dropdownWrapRefs = ref({})
const dropdownPlacement = ref(null)
const dropdownMenuRef = ref(null)

const addUserModalOpen = ref(false)
const newUser = ref({ identifier: '', password: '', role: 'member' })
const createError = ref('')
const editUserModal = ref(null)
const editForm = ref({ identifier: '', password: '' })
const editError = ref('')
const deleteConfirmUser = ref(null)

function setDropdownWrapRef(userId, el) {
  if (el) dropdownWrapRefs.value[userId] = el
  else {
    dropdownWrapRefs.value = Object.fromEntries(
      Object.entries(dropdownWrapRefs.value).filter(([k]) => k !== userId),
    )
  }
}

watch(user, (u) => {
  if (u?.role === 'admin' || u?.role === 'leader') refreshUsers()
}, { immediate: true })

function toggleRoleDropdown(userId) {
  if (openRoleDropdownId.value === userId) {
    openRoleDropdownId.value = null
    dropdownPlacement.value = null
    return
  }
  openRoleDropdownId.value = userId
  nextTick(() => {
    const wrap = dropdownWrapRefs.value[userId]
    if (wrap) {
      const rect = wrap.getBoundingClientRect()
      dropdownPlacement.value = {
        top: rect.bottom + 4,
        left: rect.left,
        minWidth: Math.max(rect.width, 96),
      }
    }
    else {
      dropdownPlacement.value = { top: 0, left: 0, minWidth: 96 }
    }
  })
}

function selectRole(userId, role) {
  pendingRoleUpdates.value = { ...pendingRoleUpdates.value, [userId]: role }
  openRoleDropdownId.value = null
  dropdownPlacement.value = null
}

function onDocumentClick(e) {
  const openId = openRoleDropdownId.value
  if (openId == null) return
  const wrap = dropdownWrapRefs.value[openId]
  const menu = dropdownMenuRef.value
  const inTrigger = wrap && wrap.contains(e.target)
  const inMenu = menu && menu.contains(e.target)
  if (!inTrigger && !inMenu) {
    openRoleDropdownId.value = null
    dropdownPlacement.value = null
  }
}

onMounted(() => {
  document.addEventListener('click', onDocumentClick)
})
onBeforeUnmount(() => {
  document.removeEventListener('click', onDocumentClick)
})

async function saveRole(id) {
  const role = roleByUserId.value[id]
  if (!role) return
  try {
    await $fetch(`/api/users/${id}`, { method: 'PATCH', body: { role } })
    await refreshUsers()
    pendingRoleUpdates.value = Object.fromEntries(
      Object.entries(pendingRoleUpdates.value).filter(([k]) => k !== id),
    )
  }
  catch {
    // could set error state
  }
}

function openAddUserModal() {
  addUserModalOpen.value = true
  newUser.value = { identifier: '', password: '', role: 'member' }
  createError.value = ''
}

function closeAddUserModal() {
  addUserModalOpen.value = false
  createError.value = ''
}

async function submitAddUser() {
  createError.value = ''
  try {
    await $fetch('/api/users', {
      method: 'POST',
      body: {
        identifier: newUser.value.identifier.trim(),
        password: newUser.value.password,
        role: newUser.value.role,
      },
    })
    closeAddUserModal()
    await refreshUsers()
  }
  catch (e) {
    createError.value = e.data?.message || e.message || 'Failed to create user'
  }
}

function openEditUser(u) {
  editUserModal.value = u
  editForm.value = { identifier: u.identifier, password: '' }
  editError.value = ''
}

async function submitEditUser() {
  if (!editUserModal.value) return
  editError.value = ''
  const id = editUserModal.value.id
  const body = { identifier: editForm.value.identifier.trim() }
  if (editForm.value.password) body.password = editForm.value.password
  try {
    await $fetch(`/api/users/${id}`, { method: 'PATCH', body })
    editUserModal.value = null
    await refreshUsers()
    // If you edited yourself, refresh current user so the header/nav shows the new identifier
    await refreshUser()
  }
  catch (e) {
    editError.value = e.data?.message || e.message || 'Failed to update user'
  }
}

function openDeleteConfirm(u) {
  deleteConfirmUser.value = u
}

async function confirmDeleteUser() {
  const u = deleteConfirmUser.value
  if (!u) return
  try {
    await $fetch(`/api/users/${u.id}`, { method: 'DELETE' })
    deleteConfirmUser.value = null
    await refreshUsers()
  }
  catch (e) {
    alert(e.data?.message || e.message || 'Failed to remove user')
  }
}
</script>
