<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import { DIFFICULTIES, MAPS } from '@/game/config'
import { isLoggedIn, login, logout } from '@/game/auth'
import { store } from '@/game/store'

interface SoloPlayer {
  userId: string
  username: string
  displayName: string
  map: string
  difficulty: string
  wave: number
  since: number
  lastSeen: number
}
interface RoomInfo {
  code: string
  mode: string
  mapId: string
  created: number
  players: { id: number; name: string }[]
}
interface AdminUser {
  id: string
  username: string
  displayName: string
  crystals: number
  createdAt: number
  lastLogin: number
  stats: { gamesPlayed: number; gamesWon: number; totalKills: number; totalScore: number; highestWave: number }
}
interface Overview {
  soloPlayers: SoloPlayer[]
  rooms: RoomInfo[]
  stats: { users: number; gamesPlayed: number; gamesWon: number; crystalsInCirculation: number }
}

const username = ref('')
const password = ref('')
const loginError = ref('')
const busy = ref(false)

const overview = ref<Overview | null>(null)
const users = ref<AdminUser[]>([])
const lastRefresh = ref<Date | null>(null)
let refreshTimer: ReturnType<typeof setInterval> | null = null

const isAdmin = computed(() => Boolean(store.auth.user && (store.auth.user as unknown as { admin?: boolean }).admin))
const mapName = (id: string): string => (MAPS as Record<string, { name: string }>)[id]?.name ?? id
const diffName = (id: string): string =>
  (DIFFICULTIES as Record<string, { name: string }>)[id]?.name ?? id

function sinceLabel(ts: number): string {
  const min = Math.max(0, Math.round((Date.now() - ts) / 60000))
  if (min < 1) return 'gerade eben'
  if (min === 1) return 'seit 1 Min.'
  if (min < 60) return `seit ${min} Min.`
  const h = Math.floor(min / 60)
  return `seit ${h} Std. ${min % 60} Min.`
}

function timeLabel(ts: number): string {
  return new Date(ts).toLocaleString('de-DE', { dateStyle: 'short', timeStyle: 'short' })
}

async function refresh(): Promise<void> {
  try {
    const [ov, us] = await Promise.all([
      fetch('/api/admin/overview', { credentials: 'same-origin' }).then((r) => (r.ok ? r.json() : null)),
      fetch('/api/admin/users?limit=100', { credentials: 'same-origin' }).then((r) => (r.ok ? r.json() : null)),
    ])
    if (ov) overview.value = ov
    if (us) users.value = us.users ?? []
    lastRefresh.value = new Date()
  } catch {
    /* server unreachable – keep last state */
  }
}

async function doLogin(): Promise<void> {
  busy.value = true
  loginError.value = ''
  const err = await login(username.value.trim(), password.value)
  busy.value = false
  if (err) loginError.value = err
}

onMounted(() => {
  refreshTimer = setInterval(() => void refresh(), 5000)
})
onBeforeUnmount(() => {
  if (refreshTimer) clearInterval(refreshTimer)
})
void refresh()
</script>

<template>
  <div class="admin">
    <header class="topbar">
      <div class="brand">🛡️ TRXTD Admin</div>
      <div class="actions">
        <span v-if="lastRefresh" class="refresh">aktualisiert {{ lastRefresh.toLocaleTimeString('de-DE') }}</span>
        <a class="link" href="/">← Zum Spiel</a>
        <button v-if="isLoggedIn()" class="btn small" @click="logout()">Abmelden</button>
      </div>
    </header>

    <!-- not logged in (guests included) -->
    <div v-if="!isLoggedIn()" class="gate">
      <form class="gate-card" @submit.prevent="doLogin">
        <h2>Admin-Anmeldung</h2>
        <p class="hint">Melde dich mit einem Konto aus <code>ADMIN_USERS</code> an.</p>
        <label class="field">
          <span>Benutzername</span>
          <input v-model="username" autocomplete="username" />
        </label>
        <label class="field">
          <span>Passwort</span>
          <input v-model="password" type="password" autocomplete="current-password" />
        </label>
        <p v-if="loginError" class="error">{{ loginError }}</p>
        <button type="submit" class="btn primary" :disabled="busy">Anmelden</button>
      </form>
    </div>

    <!-- logged in, but no admin rights -->
    <div v-else-if="!isAdmin" class="gate">
      <div class="gate-card">
        <h2>⛔ Kein Zugriff</h2>
        <p class="hint">
          Dieses Konto ist kein Administrator. Hinterlege es in der Umgebungsvariable
          <code>ADMIN_USERS</code> (Komma-getrennt) und starte den Server neu.
        </p>
      </div>
    </div>

    <!-- dashboard -->
    <div v-else class="content">
      <div class="kpis">
        <div class="kpi"><span class="v">{{ overview?.soloPlayers.length ?? 0 }}</span><span class="k">Spielt jetzt Solo</span></div>
        <div class="kpi"><span class="v">{{ overview?.rooms.length ?? 0 }}</span><span class="k">Multiplayer-Räume</span></div>
        <div class="kpi"><span class="v">{{ overview?.stats.users ?? 0 }}</span><span class="k">Accounts</span></div>
        <div class="kpi"><span class="v">{{ overview?.stats.gamesPlayed ?? 0 }}</span><span class="k">Runden gespielt</span></div>
        <div class="kpi"><span class="v">💎 {{ overview?.stats.crystalsInCirculation ?? 0 }}</span><span class="k">Kristalle im Umlauf</span></div>
      </div>

      <section class="panel">
        <h3>🎮 Spielt gerade Solo</h3>
        <p v-if="!overview?.soloPlayers.length" class="empty">Gerade spielt niemand Solo.</p>
        <table v-else>
          <thead>
            <tr><th>Spieler</th><th>Karte</th><th>Schwierigkeit</th><th>Welle</th><th>Online</th></tr>
          </thead>
          <tbody>
            <tr v-for="p in overview.soloPlayers" :key="p.userId">
              <td><b>{{ p.displayName }}</b> <span class="dim">@{{ p.username }}</span></td>
              <td>{{ mapName(p.map) }}</td>
              <td>{{ diffName(p.difficulty) }}</td>
              <td>🌊 {{ p.wave }}</td>
              <td class="live"><span class="dot" /> {{ sinceLabel(p.since) }}</td>
            </tr>
          </tbody>
        </table>
      </section>

      <section class="panel">
        <h3>👥 Multiplayer-Räume</h3>
        <p v-if="!overview?.rooms.length" class="empty">Keine offenen Räume.</p>
        <table v-else>
          <thead>
            <tr><th>Code</th><th>Modus</th><th>Karte</th><th>Spieler</th><th>Offen seit</th></tr>
          </thead>
          <tbody>
            <tr v-for="r in overview.rooms" :key="r.code">
              <td><b>{{ r.code }}</b></td>
              <td>{{ r.mode === 'coop' ? '🤝 Coop' : '⚔ 1v1' }}</td>
              <td>{{ mapName(r.mapId) }}</td>
              <td>{{ r.players.map((p) => p.name).join(', ') }}</td>
              <td>{{ sinceLabel(r.created) }}</td>
            </tr>
          </tbody>
        </table>
      </section>

      <section class="panel">
        <h3>📊 Accounts</h3>
        <table>
          <thead>
            <tr><th>Spieler</th><th>💎 Kristalle</th><th>Runden</th><th>Siege</th><th>Beste Welle</th><th>Punkte</th><th>Letzter Login</th></tr>
          </thead>
          <tbody>
            <tr v-for="u in users" :key="u.id">
              <td><b>{{ u.displayName }}</b> <span class="dim">@{{ u.username }}</span></td>
              <td>💎 {{ u.crystals }}</td>
              <td>{{ u.stats.gamesPlayed }}</td>
              <td>{{ u.stats.gamesWon }}</td>
              <td>🌊 {{ u.stats.highestWave }}</td>
              <td>{{ u.stats.totalScore.toLocaleString('de-DE') }}</td>
              <td>{{ timeLabel(u.lastLogin) }}</td>
            </tr>
          </tbody>
        </table>
      </section>
    </div>
  </div>
</template>

<style scoped>
.admin {
  min-height: 100dvh;
  background: var(--bg);
  color: var(--text);
  font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
}
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 20px;
  background: var(--panel);
  border-bottom: 1px solid var(--panel-border);
  position: sticky;
  top: 0;
  z-index: 5;
}
.brand {
  font-weight: 800;
  font-size: 17px;
}
.actions {
  display: flex;
  align-items: center;
  gap: 12px;
}
.refresh {
  color: var(--text-dim);
  font-size: 12px;
}
.link {
  color: var(--accent);
  text-decoration: none;
  font-weight: 700;
  font-size: 13.5px;
}
.gate {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: calc(100dvh - 60px);
  padding: 16px;
}
.gate-card {
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  padding: 26px 30px;
  width: 380px;
  max-width: 94vw;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.gate-card h2 {
  margin: 0;
  font-size: 19px;
}
.hint {
  margin: 0;
  color: var(--text-dim);
  font-size: 12.5px;
  line-height: 1.5;
}
.hint code {
  background: var(--panel-inset);
  border-radius: 4px;
  padding: 1px 5px;
}
.field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.field span {
  font-size: 12px;
  color: var(--text-dim);
}
.field input {
  background: var(--panel-inset);
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  padding: 9px 12px;
  color: var(--text);
  font-family: inherit;
  font-size: 14px;
  outline: none;
}
.field input:focus {
  border-color: var(--accent);
}
.error {
  margin: 0;
  color: #ff8a7a;
  font-size: 13px;
}
.btn.primary {
  background: linear-gradient(180deg, #59b34d, #3f8f37);
  border: none;
  color: #fff;
  font-weight: 800;
  padding: 10px;
  border-radius: 9px;
  cursor: pointer;
  font-family: inherit;
}
.btn.small {
  background: var(--panel-inset);
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  color: var(--text);
  font-weight: 700;
  font-size: 12.5px;
  padding: 6px 12px;
  cursor: pointer;
  font-family: inherit;
}
.content {
  max-width: 1080px;
  margin: 0 auto;
  padding: 18px 16px 40px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 10px;
}
.kpi {
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 12px;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.kpi .v {
  font-size: 22px;
  font-weight: 800;
  color: var(--accent);
}
.kpi .k {
  font-size: 12px;
  color: var(--text-dim);
}
.panel {
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 12px;
  padding: 14px 16px;
}
.panel h3 {
  margin: 0 0 10px;
  font-size: 15px;
}
.empty {
  margin: 0;
  color: var(--text-dim);
  font-size: 13px;
}
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
th {
  text-align: left;
  color: var(--text-dim);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  padding: 6px 8px;
  border-bottom: 1px solid var(--panel-border);
}
td {
  padding: 8px;
  border-bottom: 1px solid rgba(38, 49, 64, 0.5);
  white-space: nowrap;
}
.dim {
  color: var(--text-dim);
  font-size: 11.5px;
}
.live {
  color: #8ce29b;
}
.dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #4caf50;
  box-shadow: 0 0 6px #4caf50;
  margin-right: 4px;
}
@media (max-width: 640px) {
  .panel {
    overflow-x: auto;
  }
  .refresh {
    display: none;
  }
}
</style>
