<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { fetchAdminUsers, type AdminUser } from '@/services/adminUsers'
import { AuthRequestError } from '@/services/authSession'
import { useAppBannersStore } from '@/stores/appBanners'
import StatusPill from '@/components/ui/StatusPill.vue'
import UserAvatar from '@/components/ui/UserAvatar.vue'
import EmptyState from '@/components/ui/EmptyState.vue'
import CreateUserDialog from '@/components/admin/CreateUserDialog.vue'

const router = useRouter()
const appBannersStore = useAppBannersStore()

const isLoading = ref(true)
const errorMessage = ref('')
const users = ref<AdminUser[]>([])
const searchQuery = ref('')
const isCreateDialogOpen = ref(false)

const hasUsers = computed(() => users.value.length > 0)
const activeUserCount = computed(() => users.value.filter((user) => user.isActive).length)
const passwordChangeCount = computed(
  () => users.value.filter((user) => user.mustChangePassword).length,
)
const adminCount = computed(
  () =>
    users.value.filter((user) =>
      user.roles.some((role) => role.toLowerCase() === 'admin'),
    ).length,
)

const filteredUsers = computed(() => {
  const query = (searchQuery.value ?? '').trim().toLowerCase()
  if (query.length === 0) {
    return users.value
  }

  return users.value.filter((user) => {
    if (user.userName.toLowerCase().includes(query)) {
      return true
    }

    if (user.id.toLowerCase().includes(query)) {
      return true
    }

    return user.roles.some((role) => role.toLowerCase().includes(query))
  })
})

function userInitials(user: AdminUser) {
  const name = user.userName?.trim() ?? ''
  if (name.length === 0) {
    return '·'
  }

  const parts = name.split(/[\s._-]+/).filter((part) => part.length > 0)
  if (parts.length === 0) {
    return name.slice(0, 2).toUpperCase()
  }

  if (parts.length === 1) {
    const first = parts[0] as string
    return first.slice(0, 2).toUpperCase()
  }

  const first = parts[0] as string
  const second = parts[1] as string
  return `${first.charAt(0)}${second.charAt(0)}`.toUpperCase()
}

function formatRoles(roles: string[]): string {
  return roles.length > 0 ? roles.join(', ') : 'Keine Rolle'
}

async function loadUsers() {
  isLoading.value = true
  errorMessage.value = ''

  try {
    users.value = await fetchAdminUsers()
  } catch (error) {
    if (error instanceof AuthRequestError) {
      errorMessage.value = error.message

      if (error.status === 401) {
        await router.replace({
          name: 'Login',
          query: { redirect: '/admin/users' },
        })
        return
      }

      if (error.status === 403) {
        await router.replace({ name: 'Forbidden' })
        return
      }
    } else {
      errorMessage.value = 'Benutzerliste konnte nicht geladen werden.'
    }

    appBannersStore.pushError(errorMessage.value, 'Benutzerverwaltung')
  } finally {
    isLoading.value = false
  }
}

async function openUserDetail(userId: string) {
  await router.push({ name: 'AdminUserDetail', params: { userId } })
}

function openCreateDialog() {
  isCreateDialogOpen.value = true
}

function handleUserCreated(user: AdminUser) {
  users.value = [...users.value, user]
}

onMounted(() => {
  void loadUsers()
})
</script>

<template>
  <v-container fluid class="admin-users-page ui-page">
    <header class="admin-users-header ui-panel ui-panel-gradient">
      <div class="admin-users-header__copy">
        <p class="ui-kicker ui-kicker--wide">Adminbereich</p>
        <h1>Benutzerverwaltung</h1>
        <p>Alle Hoard-Konten mit Rollen, Status und Passwortwechselpflicht – read-only.</p>
      </div>

      <div class="admin-users-header__actions ui-action-row">
        <v-text-field
          v-model="searchQuery"
          variant="outlined"
          density="comfortable"
          prepend-inner-icon="mdi-magnify"
          placeholder="Benutzer, Rollen oder ID suchen"
          hide-details
          clearable
          class="admin-users-search"
        />
        <v-btn
          variant="elevated"
          color="primary"
          prepend-icon="mdi-account-plus-outline"
          :disabled="isLoading"
          @click="openCreateDialog"
        >
          Benutzer anlegen
        </v-btn>
        <v-btn
          variant="outlined"
          prepend-icon="mdi-refresh"
          :loading="isLoading"
          :disabled="isLoading"
          @click="loadUsers"
        >
          Neu laden
        </v-btn>
      </div>
    </header>

    <section v-if="!isLoading && !errorMessage" class="admin-users-stats" aria-label="Benutzerübersicht">
      <article class="admin-users-stat">
        <span class="ui-icon-tile">
          <v-icon icon="mdi-account-group-outline" size="20" />
        </span>
        <div>
          <p class="admin-users-stat__label">Konten</p>
          <p class="admin-users-stat__value">{{ users.length }}</p>
        </div>
      </article>
      <article class="admin-users-stat">
        <span class="ui-icon-tile">
          <v-icon icon="mdi-account-check-outline" size="20" />
        </span>
        <div>
          <p class="admin-users-stat__label">Aktiv</p>
          <p class="admin-users-stat__value">{{ activeUserCount }}</p>
        </div>
      </article>
      <article class="admin-users-stat">
        <span class="ui-icon-tile">
          <v-icon icon="mdi-shield-account-outline" size="20" />
        </span>
        <div>
          <p class="admin-users-stat__label">Admins</p>
          <p class="admin-users-stat__value">{{ adminCount }}</p>
        </div>
      </article>
      <article class="admin-users-stat">
        <span class="ui-icon-tile">
          <v-icon icon="mdi-lock-reset" size="20" />
        </span>
        <div>
          <p class="admin-users-stat__label">Passwortwechsel</p>
          <p class="admin-users-stat__value">{{ passwordChangeCount }}</p>
        </div>
      </article>
    </section>

    <v-alert v-if="errorMessage" type="error">
      {{ errorMessage }}
    </v-alert>

    <p v-else-if="isLoading" class="admin-users-loading">Benutzer werden geladen …</p>

    <EmptyState
      v-else-if="!hasUsers"
      icon="mdi-account-question-outline"
      title="Keine Benutzer gefunden"
    >
      Aktuell sind keine Konten vorhanden. Ein neuer Account muss vom Admin manuell angelegt werden.
    </EmptyState>

    <section v-else class="admin-users-listing ui-panel">
      <header class="admin-users-listing__head ui-toolbar">
        <div>
          <p class="admin-users-listing__title">Benutzer</p>
          <p class="admin-users-listing__meta">{{ filteredUsers.length }} von {{ users.length }} angezeigt</p>
        </div>
      </header>

      <p v-if="filteredUsers.length === 0" class="admin-users-empty-search">
        Keine Treffer für „{{ searchQuery }}".
      </p>

      <div v-else class="admin-users-table-wrap">
        <v-table class="admin-users-table">
          <thead>
            <tr>
              <th>Benutzer</th>
              <th>Rollen</th>
              <th>Aktiv</th>
              <th>Passwort</th>
              <th class="admin-users-col-actions">Aktion</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="user in filteredUsers" :key="user.id">
              <td>
                <div class="admin-users-cell-user">
                  <UserAvatar class="admin-users-cell-user__avatar" :initials="userInitials(user)" />
                  <div>
                    <p class="admin-users-cell-user__name">{{ user.userName || '(ohne Benutzername)' }}</p>
                    <p class="admin-users-cell-user__id">{{ user.id }}</p>
                  </div>
                </div>
              </td>
              <td>{{ formatRoles(user.roles) }}</td>
              <td>
                <StatusPill :variant="user.isActive ? 'success' : 'danger'">
                  {{ user.isActive ? 'Aktiv' : 'Inaktiv' }}
                </StatusPill>
              </td>
              <td>
                <StatusPill :variant="user.mustChangePassword ? 'warning' : 'info'">
                  {{ user.mustChangePassword ? 'Erforderlich' : 'Aktuell' }}
                </StatusPill>
              </td>
              <td class="admin-users-col-actions">
                <v-btn
                  size="small"
                  variant="outlined"
                  prepend-icon="mdi-arrow-right"
                  @click="openUserDetail(user.id)"
                >
                  Details
                </v-btn>
              </td>
            </tr>
          </tbody>
        </v-table>
      </div>

      <div v-if="filteredUsers.length > 0" class="admin-users-mobile-list" aria-label="Benutzerliste">
        <article v-for="user in filteredUsers" :key="user.id" class="admin-users-mobile-card">
          <header class="admin-users-mobile-head">
            <UserAvatar class="admin-users-mobile-avatar" :initials="userInitials(user)" />
            <div>
              <p class="admin-users-mobile-label">Benutzer</p>
              <h2>{{ user.userName || '(ohne Benutzername)' }}</h2>
              <p class="admin-users-mobile-id">{{ user.id }}</p>
            </div>
          </header>

          <dl class="admin-users-mobile-details">
            <div>
              <dt>Rollen</dt>
              <dd>{{ formatRoles(user.roles) }}</dd>
            </div>
            <div>
              <dt>Aktiv</dt>
              <dd>
                <StatusPill :variant="user.isActive ? 'success' : 'danger'">
                  {{ user.isActive ? 'Aktiv' : 'Inaktiv' }}
                </StatusPill>
              </dd>
            </div>
            <div>
              <dt>Passwortwechsel</dt>
              <dd>
                <StatusPill :variant="user.mustChangePassword ? 'warning' : 'info'">
                  {{ user.mustChangePassword ? 'Erforderlich' : 'Nein' }}
                </StatusPill>
              </dd>
            </div>
          </dl>

          <v-btn
            variant="outlined"
            prepend-icon="mdi-arrow-right"
            block
            @click="openUserDetail(user.id)"
          >
            Details öffnen
          </v-btn>
        </article>
      </div>
    </section>

    <CreateUserDialog v-model="isCreateDialogOpen" @created="handleUserCreated" />
  </v-container>
</template>

<style scoped>
.admin-users-page {
  --ui-page-width: 1200px;
}

/* ---------- Header ---------- */
.admin-users-header {
  --ui-gradient-angle: 120deg;
  --ui-gradient-start: color-mix(in srgb, var(--color-primary-100) 55%, var(--color-surface) 45%);
  --ui-gradient-end: var(--color-surface);
  --ui-gradient-end-stop: 65%;

  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: var(--space-6);
  align-items: end;
  padding: var(--space-7) var(--space-8);
  border-radius: var(--radius-xl);
}

.admin-users-header__copy h1 {
  margin: 0 0 var(--space-2);
  font-size: var(--font-size-2xl);
  letter-spacing: -0.015em;
}

.admin-users-header__copy p {
  margin: 0;
  color: var(--color-text-secondary);
}

.admin-users-header__actions {
  justify-content: flex-end;
  align-items: center;
}

.admin-users-search {
  flex: 1 1 280px;
  min-width: 220px;
  max-width: 380px;
}

/* ---------- Stats ---------- */
.admin-users-stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-3);
}

.admin-users-stat {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background:
    linear-gradient(
      180deg,
      color-mix(in srgb, var(--color-surface) 95%, var(--color-surface-alt) 5%),
      var(--color-surface)
    );
  box-shadow: var(--shadow-xs);
}

.admin-users-stat__label,
.admin-users-stat__value {
  margin: 0;
}

.admin-users-stat__label {
  color: var(--color-text-muted);
  font-size: var(--font-size-2xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.admin-users-stat__value {
  color: var(--color-text);
  font-size: var(--font-size-2xl);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.1;
}

/* ---------- Listing ---------- */
.admin-users-listing {
  padding: 0;
  overflow: hidden;
}

.admin-users-listing__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.admin-users-listing__title {
  margin: 0;
  color: var(--color-text);
  font-size: var(--font-size-md);
  font-weight: 600;
}

.admin-users-listing__meta {
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--font-size-xs);
}

.admin-users-empty-search {
  margin: 0;
  padding: var(--space-6);
  color: var(--color-text-secondary);
  text-align: center;
}

.admin-users-loading {
  margin: 0;
  color: var(--color-text-secondary);
}

.admin-users-table-wrap {
  overflow-x: auto;
}

.admin-users-mobile-list {
  display: none;
}

.admin-users-table {
  min-width: 920px;
  border: 0;
  border-radius: 0;
}

.admin-users-cell-user {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-3);
  align-items: center;
  min-width: 0;
}

.admin-users-cell-user__avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  background: linear-gradient(135deg, var(--color-primary-600), var(--color-primary-800));
  color: var(--color-text-on-primary);
  font-size: var(--font-size-xs);
  font-weight: 700;
  letter-spacing: 0.02em;
}

.admin-users-cell-user__name,
.admin-users-cell-user__id {
  margin: 0;
}

.admin-users-cell-user__name {
  color: var(--color-text);
  font-weight: 600;
}

.admin-users-cell-user__id {
  color: var(--color-text-muted);
  font-family: var(--font-family-mono);
  font-size: var(--font-size-2xs);
  overflow-wrap: anywhere;
}

.admin-users-col-actions {
  text-align: right;
  white-space: nowrap;
}

.ui-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
}

@media (prefers-reduced-motion: no-preference) {
  .admin-users-header,
  .admin-users-stat,
  .admin-users-listing {
    animation: ui-soft-enter 280ms both;
  }

  .admin-users-stat:nth-child(2) { animation-delay: 60ms; }
  .admin-users-stat:nth-child(3) { animation-delay: 120ms; }
  .admin-users-stat:nth-child(4) { animation-delay: 180ms; }
  .admin-users-listing { animation-delay: 220ms; }
}

@media (width <= 1100px) {
  .admin-users-header {
    grid-template-columns: 1fr;
    align-items: flex-start;
  }

  .admin-users-header__actions {
    justify-content: flex-start;
  }

  .admin-users-stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (width <= 960px) {
  .admin-users-header {
    padding: var(--space-6);
  }
}

@media (width <= 600px) {
  .admin-users-header {
    padding: var(--space-5);
  }

  .admin-users-search {
    flex: 1 1 100%;
    max-width: none;
  }

  .admin-users-stats {
    grid-template-columns: 1fr;
  }

  .admin-users-listing {
    overflow: hidden;
  }

  .admin-users-table-wrap {
    display: none;
  }

  .admin-users-mobile-list {
    display: grid;
    gap: var(--space-3);
    padding: var(--space-4);
  }

  .admin-users-mobile-card {
    display: grid;
    gap: var(--space-4);
    min-width: 0;
    padding: var(--space-4);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background-color: var(--color-surface);
    box-shadow: var(--shadow-xs);
  }

  .admin-users-mobile-head {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-3);
    align-items: center;
    min-width: 0;
  }

  .admin-users-mobile-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: var(--radius-full);
    background: linear-gradient(135deg, var(--color-primary-600), var(--color-primary-800));
    color: var(--color-text-on-primary);
    font-size: var(--font-size-sm);
    font-weight: 700;
  }

  .admin-users-mobile-label,
  .admin-users-mobile-head h2,
  .admin-users-mobile-id,
  .admin-users-mobile-details {
    margin: 0;
  }

  .admin-users-mobile-label {
    color: var(--color-text-muted);
    font-size: var(--font-size-2xs);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
  }

  .admin-users-mobile-head h2 {
    color: var(--color-text);
    font-size: var(--font-size-lg);
    font-weight: 600;
    overflow-wrap: anywhere;
  }

  .admin-users-mobile-id {
    color: var(--color-text-muted);
    font-family: var(--font-family-mono);
    font-size: var(--font-size-2xs);
    overflow-wrap: anywhere;
  }

  .admin-users-mobile-details {
    display: grid;
    gap: var(--space-3);
  }

  .admin-users-mobile-details div {
    display: grid;
    gap: var(--space-1);
    padding-bottom: var(--space-3);
    border-bottom: 1px solid var(--color-border-subtle);
  }

  .admin-users-mobile-details div:last-child {
    padding-bottom: 0;
    border-bottom: none;
  }

  .admin-users-mobile-details dt {
    color: var(--color-text-muted);
    font-size: var(--font-size-xs);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }

  .admin-users-mobile-details dd {
    margin: 0;
    color: var(--color-text);
    overflow-wrap: anywhere;
  }
}
</style>
