<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useApi } from '@/composables/useApi'
import { useToastStore } from '@/stores/toast'
import type { TeamMember, Role } from '@/types'
import Panel from '@/components/ds/data/Panel.vue'
import Button from '@/components/ds/core/Button.vue'
import Badge from '@/components/ds/core/Badge.vue'
import Input from '@/components/ds/forms/Input.vue'
import Select from '@/components/ds/forms/Select.vue'
import EmptyState from '@/components/ds/feedback/EmptyState.vue'

const api = useApi()
const toast = useToastStore()

const members = ref<TeamMember[]>([])
const roles = ref<Role[]>([])
const isLoading = ref(false)
const showInvite = ref(false)
const inviteEmail = ref('')
const inviteRole = ref('')
const inviting = ref(false)

function roleTone(roleName: string): 'accent' | 'info' | 'neutral' {
  switch (roleName.toLowerCase()) {
    case 'owner': return 'accent'
    case 'admin': return 'info'
    default: return 'neutral'
  }
}

async function fetchTeam() {
  isLoading.value = true
  try {
    const data = await api.get<{ members: TeamMember[]; roles: Role[] }>('/team')
    members.value = data.members ?? []
    roles.value = data.roles ?? []
  } catch {
    toast.error('Failed to load team members')
  } finally {
    isLoading.value = false
  }
}

async function sendInvite() {
  if (!inviteEmail.value.trim() || !inviteRole.value) return
  inviting.value = true
  try {
    await api.post('/team/invite', {
      email: inviteEmail.value.trim(),
      role_id: inviteRole.value,
    })
    inviteEmail.value = ''
    inviteRole.value = ''
    showInvite.value = false
    toast.success('Invitation sent')
    await fetchTeam()
  } catch {
    toast.error('Failed to send invitation')
  } finally {
    inviting.value = false
  }
}

async function removeMember(member: TeamMember) {
  if (!confirm(`Remove ${member.username} from the team?`)) return
  try {
    await api.del(`/team/${member.id}`)
    toast.success(`${member.username} removed from team`)
    await fetchTeam()
  } catch {
    toast.error(`Failed to remove ${member.username}`)
  }
}

onMounted(() => {
  fetchTeam()
})

const roleOptions = computed(() =>
  roles.value.map((r) => ({ value: r.id, label: r.role_name }))
)
</script>

<template>
  <div class="team">
    <!-- Page head -->
    <div class="page__head">
      <div>
        <div class="t-eyebrow">Management</div>
        <h1 class="page__title">Team</h1>
      </div>
      <div class="page__actions">
        <Button
          variant="secondary"
          size="sm"
          icon="refresh-cw"
          :loading="isLoading"
          @click="fetchTeam"
        >
          Refresh
        </Button>
        <Button
          size="sm"
          icon="mail"
          @click="showInvite = !showInvite"
        >
          Invite member
        </Button>
      </div>
    </div>

    <!-- Invite panel -->
    <Panel v-if="showInvite" title="Invite a team member" eyebrow="New invite">
      <form @submit.prevent="sendInvite" class="invite-form">
        <Input
          v-model="inviteEmail"
          label="Email address"
          type="email"
          placeholder="team@example.com"
          :required="true"
          style="flex: 1"
        />
        <div class="invite-role">
          <span class="cc-field__label">Role</span>
          <Select
            v-model="inviteRole"
            :options="[{ value: '', label: 'Select role...' }, ...roleOptions]"
          />
        </div>
        <div class="invite-action">
          <!-- spacer to align with inputs -->
          <span class="cc-field__label">&nbsp;</span>
          <Button type="submit" size="md" :loading="inviting">
            {{ inviting ? 'Sending...' : 'Send invite' }}
          </Button>
        </div>
      </form>
    </Panel>

    <!-- Team table -->
    <Panel :flush-body="true" title="Members" :subtitle="members.length + ' total'">
      <!-- Empty state -->
      <EmptyState
        v-if="!isLoading && members.length === 0"
        icon="users"
        title="No team members"
        description="Invite someone to get started."
      >
        <template #action>
          <Button size="sm" icon="mail" @click="showInvite = true">Invite member</Button>
        </template>
      </EmptyState>

      <!-- Loading skeleton -->
      <div v-else-if="isLoading" class="table-loading">
        <div v-for="i in 3" :key="i" class="skeleton-row" />
      </div>

      <!-- Table -->
      <table v-else class="cc-table">
        <thead>
          <tr>
            <th>Member</th>
            <th>Email</th>
            <th>Role</th>
            <th>Status</th>
            <th class="col-actions">Actions</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="member in members" :key="member.id">
            <td>
              <div class="member-id">
                <span class="member-avatar">{{ (member.username ?? '?')[0]?.toUpperCase() ?? '?' }}</span>
                <span class="member-name">{{ member.username }}</span>
              </div>
            </td>
            <td class="cell-mono">{{ member.email }}</td>
            <td>
              <Badge :tone="roleTone(member.role_name)">{{ member.role_name }}</Badge>
            </td>
            <td>
              <Badge :tone="member.accepted_at ? 'online' : 'warn'" :dot="true">
                {{ member.accepted_at ? 'Active' : 'Pending' }}
              </Badge>
            </td>
            <td class="col-actions">
              <Button
                variant="ghost"
                size="sm"
                icon="trash-2"
                title="Remove member"
                @click="removeMember(member)"
              />
            </td>
          </tr>
        </tbody>
      </table>
    </Panel>
  </div>
</template>

<style scoped>
.team { max-width: 1100px; margin: 0 auto; display: flex; flex-direction: column; gap: 18px; }

.page__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; row-gap: 10px; }
.page__title { font-size: var(--text-3xl); font-weight: 700; letter-spacing: -0.02em; color: var(--text-primary); margin-top: 5px; }
.page__actions { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }

/* Invite form */
.invite-form { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; }
.invite-role { display: flex; flex-direction: column; gap: 6px; min-width: 180px; }
.invite-action { display: flex; flex-direction: column; gap: 6px; }

/* Table */
.cc-table { width: 100%; border-collapse: collapse; }
.cc-table th {
  padding: 10px 16px;
  text-align: left;
  font-size: var(--text-xs); font-weight: 600; color: var(--text-tertiary);
  text-transform: uppercase; letter-spacing: var(--tracking-wider);
  border-bottom: 1px solid var(--border-subtle);
}
.cc-table td {
  padding: 11px 16px;
  font-size: var(--text-sm); color: var(--text-secondary);
  border-bottom: 1px solid var(--border-subtle);
}
.cc-table tbody tr:last-child td { border-bottom: 0; }
.cc-table tbody tr:hover td { background: var(--surface-hover); }
.col-actions { text-align: right; width: 56px; }

.member-id { display: flex; align-items: center; gap: 10px; }
.member-avatar {
  width: 28px; height: 28px; border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center; flex: none;
  background: var(--accent-soft); color: var(--accent-text);
  font-size: var(--text-xs); font-weight: 700;
}
.member-name { font-size: var(--text-sm); font-weight: 500; color: var(--text-primary); }
.cell-mono { font-family: var(--font-mono); font-size: var(--text-xs) !important; color: var(--text-tertiary) !important; }

/* Loading skeleton */
.table-loading { padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.skeleton-row { height: 40px; border-radius: var(--radius-md); background: var(--surface-raised-2); animation: cc-skeleton 1.4s ease-in-out infinite; }
@keyframes cc-skeleton { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }
</style>
