<script setup lang="ts">
// Partner team. Strict port of PartnerTeamScreen + PartnerTeammateRowActions
// (partner-screens.jsx lines 1054-1099 + 1431-1524). Owner row (Anne Baslund)
// has destructive actions (Suspend, Remove) disabled with "owner" mono tag.



import type { TeamMember } from '~/components/partner/TeammatePanel.vue'

const toast = useToast()
const { request } = useApiFetch()

const inviteOpen = ref(false)
const openMember = ref<TeamMember | null>(null)

// Real partner team from platform-api (proxied via /api/partner/users). The
// enriched response adds mfaEnabled (live Authentik lookup), accessLevel, and
// accessCount per user.
interface PartnerUserDoc {
  _id: string
  authentikSubjectId: string
  email: string
  name: string
  role: string
  active: boolean
  lastLoginAt?: string
  createdAt?: string
  mfaEnabled?: boolean | null
  accessLevel?: 'all' | 'scoped'
  accessCount?: number | null
}

const { data: rawTeam, refresh } = await useFetch<PartnerUserDoc[]>('/api/partner/users', {
  key: 'partner-users',
  default: () => [],
})

// Real customer count for the "all (N)" / "N of M" access labels.
const { tenants } = usePartnerTenants()

function lastSeenLabel(iso?: string): string {
  if (!iso) return 'never'
  const ms = Date.now() - new Date(iso).getTime()
  if (ms < 60_000) return 'just now'
  const m = Math.floor(ms / 60_000)
  if (m < 60) return `${m} min ago`
  const h = Math.floor(m / 60)
  if (h < 24) return `${h} h ago`
  const d = Math.floor(h / 24)
  return `${d} d ago`
}

const members = computed<TeamMember[]>(() =>
  (rawTeam.value ?? []).map((u) => ({
    id: u.authentikSubjectId,
    name: u.name,
    email: u.email,
    role: u.role === 'admin' ? 'Partner admin' : u.role === 'owner' ? 'Owner' : 'Partner staff',
    access: u.accessLevel === 'scoped' ? 'specific' : 'all',
    accessCount: u.accessCount ?? null,
    mfa: u.mfaEnabled === true ? 'enabled' : u.mfaEnabled === false ? 'disabled' : 'unknown',
    lastSeen: lastSeenLabel(u.lastLoginAt),
    isOwner: u.role === 'owner',
  })),
)

function accessLabel(m: TeamMember) {
  const total = tenants.value?.length ?? 0
  if (m.access === 'none') return 'no access'
  if (m.access === 'all') return `all (${total})`
  return `${m.accessCount ?? 0} of ${total}`
}

async function onSent(payload: { name: string; email: string; role: string }) {
  try {
    await request('/api/partner/users', {
      method: 'POST',
      body: { name: payload.name, email: payload.email },
    })
    toast.ok('Invitation sent', `Invite sent to ${payload.email}`)
    await Promise.all([refresh(), refreshNuxtData('partner-users')])
  } catch (e: unknown) {
    const err = e as { data?: { message?: string }; statusMessage?: string }
    toast.bad('Invite failed', err.data?.message || err.statusMessage || 'Could not send invitation')
  }
}

async function removeMember(m: TeamMember) {
  try {
    await request(`/api/partner/users/${m.id}`, { method: 'DELETE' })
    toast.ok('Removed', `${m.name} removed from the team`)
    openMember.value = null
    await Promise.all([refresh(), refreshNuxtData('partner-users')])
  } catch (e: unknown) {
    const err = e as { data?: { message?: string }; statusMessage?: string }
    toast.bad('Remove failed', err.data?.message || err.statusMessage || 'Could not remove teammate')
  }
}

// Row actions popover · mirrors PartnerTeammateRowActions (lines 1431-1524).
const menuFor = ref<string | null>(null)
const menuPos = ref<{ top: number; right: number }>({ top: 0, right: 0 })

function openMenu(m: TeamMember, e: MouseEvent) {
  e.stopPropagation()
  const btn = (e.currentTarget as HTMLElement).getBoundingClientRect()
  menuPos.value = { top: btn.bottom + 4, right: window.innerWidth - btn.right }
  menuFor.value = menuFor.value === m.id ? null : m.id
}

function actionsFor(m: TeamMember) {
  return [
    { i: 'users',    l: 'View details',       fn: () => openMember.value = m },
    { i: 'brush',    l: 'Change role…',       fn: () => openMember.value = m },
    { i: 'building', l: 'Customer access…',   fn: () => openMember.value = m },
    { sep: true },
    { i: 'refresh',  l: 'Resend invitation',  fn: () => toast.info('Invitation resent', m.email) },
    { i: 'shield',   l: 'Reset MFA',          fn: () => toast.warn('MFA reset', `${m.name} must enrol again on next sign-in`) },
    { i: 'key',      l: 'Reset password',     fn: () => toast.info('Password reset', `Email sent to ${m.email}`) },
    { sep: true },
    { i: 'x',        l: 'Suspend account',    fn: () => toast.warn('Account suspended', m.name), disabled: m.isOwner },
    { i: 'trash',    l: 'Remove from team',   danger: true, fn: () => removeMember(m), disabled: m.isOwner },
  ]
}

function closeMenu() { menuFor.value = null }

onMounted(() => {
  const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') closeMenu() }
  const onScroll = () => closeMenu()
  document.addEventListener('keydown', onKey)
  document.addEventListener('click', closeMenu)
  window.addEventListener('scroll', onScroll, true)
  window.addEventListener('resize', onScroll)
  onBeforeUnmount(() => {
    document.removeEventListener('keydown', onKey)
    document.removeEventListener('click', closeMenu)
    window.removeEventListener('scroll', onScroll, true)
    window.removeEventListener('resize', onScroll)
  })
})
</script>

<template>
  <div>
    <PageHeader
      eyebrow="People"
      title="Partner team"
      subtitle="People at NordicMSP with access to the partner console and your customers."
    >
      <template #actions>
        <UiButton variant="primary" @click="inviteOpen = true">
          <template #leading><UiIcon name="plus" :size="14" /></template>
          Invite teammate
        </UiButton>
      </template>
    </PageHeader>

    <div class="content">
      <Card :pad="0">
        <table class="dtable">
          <thead>
            <tr>
              <th>Name</th>
              <th>Role</th>
              <th>Customer access</th>
              <th>MFA</th>
              <th>Last seen</th>
              <th class="action-col" />
            </tr>
          </thead>
          <tbody>
            <tr
              v-for="m in members"
              :key="m.id"
              @click="openMember = m"
            >
              <td>
                <div class="user-cell">
                  <Avatar :name="m.name" :size="28" />
                  <div>
                    <div class="user-name">{{ m.name }}</div>
                    <Mono dim>{{ m.email }}</Mono>
                  </div>
                </div>
              </td>
              <td>
                <Badge :tone="m.role === 'Partner admin' ? 'invert' : 'neutral'">{{ m.role }}</Badge>
              </td>
              <td><Mono>{{ accessLabel(m) }}</Mono></td>
              <td><Badge :tone="m.mfa === 'enabled' ? 'ok' : m.mfa === 'disabled' ? 'warn' : 'neutral'" dot>{{ m.mfa }}</Badge></td>
              <td><Mono dim>{{ m.lastSeen }}</Mono></td>
              <td class="action-col" @click.stop>
                <button class="kebab" @click="openMenu(m, $event)">
                  <UiIcon name="more" :size="14" />
                </button>
              </td>
            </tr>
          </tbody>
        </table>
      </Card>
    </div>

    <!-- Portaled action menu -->
    <Teleport to="body">
      <div
        v-if="menuFor"
        class="menu"
        :style="{ top: menuPos.top + 'px', right: menuPos.right + 'px' }"
        @click.stop
      >
        <template v-for="(it, i) in actionsFor(members.find(m => m.id === menuFor)!)" :key="i">
          <div v-if="it.sep" class="menu-sep" />
          <button
            v-else
            class="menu-item"
            :class="{ danger: it.danger, disabled: it.disabled }"
            :disabled="it.disabled"
            @click="(it.fn?.(), closeMenu())"
          >
            <UiIcon :name="(it.i as any)" :size="13" />
            <span>{{ it.l }}</span>
            <Mono
              v-if="members.find(m => m.id === menuFor)?.isOwner && (it.l?.startsWith('Suspend') || it.l?.startsWith('Remove'))"
              dim
              class="owner-tag"
            >owner</Mono>
          </button>
        </template>
      </div>
    </Teleport>

    <PartnerInviteTeammateModal :open="inviteOpen" @close="inviteOpen = false" @sent="onSent" />
    <PartnerTeammatePanel :member="openMember" @close="openMember = null" />
  </div>
</template>

<style scoped>
.content { padding: 24px 40px 64px; }

.dtable { width: 100%; border-collapse: collapse; }
.dtable th {
  text-align: left;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-mute);
  font-weight: 500;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
}
.dtable th.action-col { width: 40px; }
.dtable td {
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
  vertical-align: middle;
}
.dtable tbody tr { cursor: pointer; transition: background 80ms; }
.dtable tbody tr:hover { background: var(--row-hover); }

.user-cell { display: flex; align-items: center; gap: 12px; }
.user-name { font-size: 13px; font-weight: 500; }

.kebab {
  background: transparent;
  border: none;
  color: var(--text-mute);
  padding: 4px;
  border-radius: 4px;
  cursor: pointer;
}
.kebab:hover { background: var(--row-hover); color: var(--text); }
</style>

<style>
/* Portaled menu — global because Teleport-ed to body */
.menu {
  position: fixed;
  min-width: 220px;
  padding: 4px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
  z-index: 100;
}
.menu .menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border-radius: 5px;
  background: transparent;
  border: none;
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
  text-align: left;
  color: var(--text);
}
.menu .menu-item:hover:not(:disabled) { background: var(--row-hover); }
.menu .menu-item.danger { color: var(--bad); }
.menu .menu-item.disabled, .menu .menu-item:disabled { color: var(--text-mute); cursor: not-allowed; opacity: 0.5; }
.menu .menu-item svg { color: var(--text-mute); flex-shrink: 0; }
.menu .menu-item.danger svg { color: var(--bad); }
.menu .menu-item span { flex: 1; }
.menu .menu-sep { height: 1px; background: var(--border); margin: 4px 0; }
.menu .owner-tag { font-size: 9px; }
</style>
