<template>
  <div>
    <h1 class="text-xl font-semibold text-white mb-1">User-Management</h1>
    <p class="text-sm text-gray-500 mb-6">
      User-Liste, Plan-Status, Ban / Soft-Delete. Anonym -- nur Nicknames, niemals E-Mail oder Klarname.
    </p>

    <!-- Filter-Bar -->
    <div class="flex flex-wrap items-center gap-3 mb-4">
      <UInput
        v-model="searchInput"
        placeholder="Suche Nickname / Username"
        icon="heroicons:magnifying-glass"
        size="sm"
        class="w-72"
        @keyup.enter="reload"
      />
      <USelect
        v-model="planFilter"
        :items="planOptions"
        placeholder="Alle Pläne"
        size="sm"
        class="w-40"
        @update:model-value="reload"
      />
      <UButton size="sm" color="neutral" variant="soft" @click="reload">
        Aktualisieren
      </UButton>
      <span class="text-xs text-gray-500 ml-auto">
        {{ rows.length }} User geladen
      </span>
    </div>

    <!-- Tabelle -->
    <div class="rounded-lg border border-gray-800 bg-gray-900 overflow-hidden">
      <UTable
        :data="rows"
        :columns="columns"
        :loading="loading"
        :empty-state="{ icon: 'heroicons:users', label: 'Keine User gefunden.' }"
        class="w-full"
      >
        <template #nickname-cell="{ row }">
          <div class="flex items-center gap-2">
            <UAvatar
              :src="row.original.avatar ?? undefined"
              :alt="row.original.nickname ?? row.original.username ?? ''"
              size="xs"
            />
            <div class="flex flex-col">
              <span class="text-sm text-white">
                {{ row.original.nickname ?? row.original.username ?? "—" }}
              </span>
              <span v-if="row.original.username && row.original.nickname" class="text-xs text-gray-500">
                {{ row.original.username }}
              </span>
            </div>
          </div>
        </template>

        <template #plan-cell="{ row }">
          <UBadge
            :color="planBadgeColor(row.original.plan)"
            variant="subtle"
            size="xs"
            class="uppercase"
          >
            {{ row.original.plan }}
          </UBadge>
        </template>

        <template #streak-cell="{ row }">
          <span class="text-sm text-gray-300">{{ row.original.streak }}</span>
        </template>

        <template #status-cell="{ row }">
          <UBadge
            v-if="row.original.deletedAt"
            color="neutral"
            variant="subtle"
            size="xs"
          >
            gelöscht
          </UBadge>
          <UBadge
            v-else-if="row.original.banned"
            color="error"
            variant="subtle"
            size="xs"
          >
            gebannt
          </UBadge>
          <UBadge v-else color="success" variant="subtle" size="xs">
            aktiv
          </UBadge>
        </template>

        <template #createdAt-cell="{ row }">
          <span class="text-xs text-gray-400">
            {{ formatDate(row.original.createdAt) }}
          </span>
        </template>

        <template #actions-cell="{ row }">
          <UDropdownMenu :items="rowActions(row.original)">
            <UButton
              icon="heroicons:ellipsis-horizontal"
              size="xs"
              color="neutral"
              variant="ghost"
            />
          </UDropdownMenu>
        </template>
      </UTable>
    </div>

    <!-- Pagination -->
    <div v-if="nextCursor" class="mt-4 flex justify-center">
      <UButton
        size="sm"
        color="neutral"
        variant="soft"
        :loading="loadingMore"
        @click="loadMore"
      >
        Weitere laden
      </UButton>
    </div>

    <!-- Plan-ändern Modal -->
    <UModal v-model:open="planModalOpen" title="Plan ändern">
      <template #body>
        <p class="text-sm text-gray-400 mb-4">
          Aktiver User: <strong>{{ selectedUser?.nickname ?? selectedUser?.username ?? selectedUser?.id }}</strong>
        </p>
        <USelect v-model="newPlan" :items="planChangeOptions" placeholder="Neuer Plan" />
      </template>
      <template #footer>
        <div class="flex gap-2 justify-end w-full">
          <UButton color="neutral" variant="ghost" @click="planModalOpen = false">
            Abbrechen
          </UButton>
          <UButton color="primary" :loading="acting" @click="confirmPlanChange">
            Speichern
          </UButton>
        </div>
      </template>
    </UModal>

    <!-- Ban-Confirm Modal -->
    <UModal v-model:open="banModalOpen" :title="banDialogTitle">
      <template #body>
        <p class="text-sm text-gray-300">
          User <strong>{{ selectedUser?.nickname ?? selectedUser?.username }}</strong>
          {{ selectedUser?.banned ? "wieder freischalten" : "wirklich bannen" }}?
        </p>
        <UInput
          v-if="!selectedUser?.banned"
          v-model="banReason"
          placeholder="Grund (optional)"
          class="mt-3"
        />
      </template>
      <template #footer>
        <div class="flex gap-2 justify-end w-full">
          <UButton color="neutral" variant="ghost" @click="banModalOpen = false">
            Abbrechen
          </UButton>
          <UButton :color="selectedUser?.banned ? 'success' : 'error'" :loading="acting" @click="confirmBan">
            {{ selectedUser?.banned ? "Freischalten" : "Bannen" }}
          </UButton>
        </div>
      </template>
    </UModal>

    <!-- Soft-Delete-Confirm Modal -->
    <UModal v-model:open="deleteModalOpen" title="Soft-Delete (DSGVO)">
      <template #body>
        <p class="text-sm text-gray-300">
          User <strong>{{ selectedUser?.nickname ?? selectedUser?.username }}</strong> wird soft-gelöscht:
        </p>
        <ul class="text-xs text-gray-500 mt-2 space-y-1 list-disc pl-5">
          <li>Nickname &rarr; null, Avatar &rarr; null, Demographie &rarr; null</li>
          <li>Username &rarr; "deleted-{shortid}"</li>
          <li>deletedAt &rarr; jetzt</li>
          <li>Auth-Account bleibt zunächst (separate Operation)</li>
        </ul>
        <p class="text-xs text-error-400 mt-3">Diese Aktion ist nicht rückgängig zu machen.</p>
      </template>
      <template #footer>
        <div class="flex gap-2 justify-end w-full">
          <UButton color="neutral" variant="ghost" @click="deleteModalOpen = false">
            Abbrechen
          </UButton>
          <UButton color="error" :loading="acting" @click="confirmDelete">
            Soft-Delete bestätigen
          </UButton>
        </div>
      </template>
    </UModal>
  </div>
</template>

<script setup lang="ts">
definePageMeta({ middleware: "admin-auth" })

type AdminUserRow = {
  id: string
  nickname: string | null
  username: string | null
  avatar: string | null
  plan: string
  streak: number
  banned: boolean
  bannedAt: string | null
  deletedAt: string | null
  createdAt: string
  lyraVoiceId: string | null
}

type ListResponse = {
  items: AdminUserRow[]
  nextCursor: string | null
}

// ─── State ──────────────────────────────────────────────────────────────────

const rows = ref<AdminUserRow[]>([])
const nextCursor = ref<string | null>(null)
const loading = ref(false)
const loadingMore = ref(false)
const acting = ref(false)

const searchInput = ref("")
const planFilter = ref<string | undefined>(undefined)

const planOptions = [
  { label: "Alle Pläne", value: "" },
  { label: "Free", value: "free" },
  { label: "Pro", value: "pro" },
  { label: "Legend", value: "legend" },
]

const planChangeOptions = [
  { label: "Free", value: "free" },
  { label: "Pro", value: "pro" },
  { label: "Legend", value: "legend" },
]

// Modals
const planModalOpen = ref(false)
const banModalOpen = ref(false)
const deleteModalOpen = ref(false)
const selectedUser = ref<AdminUserRow | null>(null)
const newPlan = ref<string>("free")
const banReason = ref("")
const banDialogTitle = computed(() =>
  selectedUser.value?.banned ? "User freischalten" : "User bannen",
)

// ─── Columns ────────────────────────────────────────────────────────────────

const columns = [
  { accessorKey: "nickname", header: "User", id: "nickname" },
  { accessorKey: "plan", header: "Plan", id: "plan" },
  { accessorKey: "streak", header: "Streak", id: "streak" },
  { accessorKey: "status", header: "Status", id: "status" },
  { accessorKey: "createdAt", header: "Beigetreten", id: "createdAt" },
  { accessorKey: "actions", header: "", id: "actions" },
]

// ─── Helpers ────────────────────────────────────────────────────────────────

function planBadgeColor(plan: string): "primary" | "success" | "warning" | "neutral" {
  if (plan === "legend") return "warning"
  if (plan === "pro") return "primary"
  if (plan === "free") return "neutral"
  return "neutral"
}

function formatDate(d: string): string {
  if (!d) return "—"
  try {
    return new Date(d).toLocaleDateString("de-DE", {
      year: "numeric",
      month: "short",
      day: "numeric",
    })
  } catch {
    return "—"
  }
}

function rowActions(user: AdminUserRow) {
  const items: Array<Array<{ label: string; icon: string; onSelect: () => void }>> = [
    [
      {
        label: "Plan ändern",
        icon: "heroicons:star",
        onSelect: () => openPlanModal(user),
      },
      {
        label: user.banned ? "Bann aufheben" : "Bannen",
        icon: user.banned ? "heroicons:lock-open" : "heroicons:lock-closed",
        onSelect: () => openBanModal(user),
      },
    ],
    [
      {
        label: "Soft-Delete",
        icon: "heroicons:trash",
        onSelect: () => openDeleteModal(user),
      },
    ],
  ]
  return items
}

// ─── Data ───────────────────────────────────────────────────────────────────

async function fetchPage(opts: { append: boolean }): Promise<void> {
  const params: Record<string, string> = {}
  if (searchInput.value.trim()) params.q = searchInput.value.trim()
  if (planFilter.value && planFilter.value !== "") params.plan = planFilter.value
  if (opts.append && nextCursor.value) params.cursor = nextCursor.value

  const res = await $fetch<ListResponse>("/api/users", { params })
  if (opts.append) {
    rows.value = [...rows.value, ...res.items]
  } else {
    rows.value = res.items
  }
  nextCursor.value = res.nextCursor
}

async function reload(): Promise<void> {
  loading.value = true
  try {
    nextCursor.value = null
    await fetchPage({ append: false })
  } catch (err) {
    console.error("[users] load failed:", err)
  } finally {
    loading.value = false
  }
}

async function loadMore(): Promise<void> {
  if (!nextCursor.value || loadingMore.value) return
  loadingMore.value = true
  try {
    await fetchPage({ append: true })
  } finally {
    loadingMore.value = false
  }
}

// ─── Actions ────────────────────────────────────────────────────────────────

function openPlanModal(user: AdminUserRow): void {
  selectedUser.value = user
  newPlan.value = user.plan
  planModalOpen.value = true
}

function openBanModal(user: AdminUserRow): void {
  selectedUser.value = user
  banReason.value = ""
  banModalOpen.value = true
}

function openDeleteModal(user: AdminUserRow): void {
  selectedUser.value = user
  deleteModalOpen.value = true
}

async function confirmPlanChange(): Promise<void> {
  if (!selectedUser.value) return
  acting.value = true
  try {
    const updated = await $fetch<AdminUserRow>(`/api/users/${selectedUser.value.id}`, {
      method: "PATCH",
      body: { plan: newPlan.value },
    })
    mergeRow(updated)
    planModalOpen.value = false
  } catch (err) {
    console.error("[users] plan-change failed:", err)
  } finally {
    acting.value = false
  }
}

async function confirmBan(): Promise<void> {
  if (!selectedUser.value) return
  acting.value = true
  try {
    const newBanned = !selectedUser.value.banned
    const updated = await $fetch<AdminUserRow>(`/api/users/${selectedUser.value.id}`, {
      method: "PATCH",
      body: {
        banned: newBanned,
        bannedReason: newBanned && banReason.value ? banReason.value : null,
      },
    })
    mergeRow(updated)
    banModalOpen.value = false
  } catch (err) {
    console.error("[users] ban-toggle failed:", err)
  } finally {
    acting.value = false
  }
}

async function confirmDelete(): Promise<void> {
  if (!selectedUser.value) return
  acting.value = true
  try {
    await $fetch(`/api/users/${selectedUser.value.id}`, { method: "DELETE" })
    // Soft-deleted user fliegt aus der Liste (default: includeDeleted=false)
    rows.value = rows.value.filter((r) => r.id !== selectedUser.value!.id)
    deleteModalOpen.value = false
  } catch (err) {
    console.error("[users] soft-delete failed:", err)
  } finally {
    acting.value = false
  }
}

function mergeRow(updated: AdminUserRow): void {
  const idx = rows.value.findIndex((r) => r.id === updated.id)
  if (idx >= 0) rows.value[idx] = updated
}

// ─── Init ───────────────────────────────────────────────────────────────────

onMounted(() => {
  reload()
})
</script>
