<script setup lang="ts">
import { computed, nextTick, watch } from 'vue'
import { RouterLink, useRoute, useRouter } from 'vue-router'
import { useNotificationSnapshot } from '../api/notifications'
import { useOpenClawOverviewQuery } from '../api/openclawRuntime'
import {
  Ban,
  Bell,
  BellOff,
  CheckCheck,
  ChevronRight,
  CircleCheckBig,
  Loader2,
  ShieldCheck,
  UserRound,
} from '@lucide/vue'
import AsyncStatePanel from '../components/mission-control/AsyncStatePanel.vue'

const router = useRouter()
const route = useRoute()
const overviewQuery = useOpenClawOverviewQuery()
const {
  query: notificationQuery,
  markAsRead,
  markAllAsRead,
  markingAllRead,
} = useNotificationSnapshot()
const notifications = computed(() => notificationQuery.data.value?.notifications ?? [])
const unreadCount = computed(() => Number(notificationQuery.data.value?.unreadCount ?? 0))
const requestedNotificationId = computed(() =>
  typeof route.query.notification === 'string' ? route.query.notification : '',
)

const sortedNotifications = computed(() => {
  return [...notifications.value].sort(
    (a, b) => {
      if (a.id === requestedNotificationId.value) return -1
      if (b.id === requestedNotificationId.value) return 1
      return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
    },
  )
})
const pendingApprovals = computed(() =>
  overviewQuery.data.value?.approvals.items.filter(item => item.status === 'pending') ?? [],
)

function typeIcon(type: string) {
  switch (type) {
    case 'task_assigned': return UserRound
    case 'task_review': return CircleCheckBig
    case 'task_blocked': return Ban
    default: return Bell
  }
}

function typeTone(type: string): string {
  switch (type) {
    case 'task_assigned': return 'assigned'
    case 'task_review': return 'review'
    case 'task_blocked': return 'blocked'
    default: return 'default'
  }
}

function timeAgo(dateStr: string): string {
  const now = Date.now()
  const then = new Date(dateStr).getTime()
  const diffSec = Math.floor((now - then) / 1000)
  if (diffSec < 60) return 'vor ' + diffSec + ' Sek'
  const diffMin = Math.floor(diffSec / 60)
  if (diffMin < 60) return 'vor ' + diffMin + ' Min'
  const diffHr = Math.floor(diffMin / 60)
  if (diffHr < 24) return 'vor ' + diffHr + ' Std'
  const diffDay = Math.floor(diffHr / 24)
  return 'vor ' + diffDay + ' Tag' + (diffDay > 1 ? 'en' : '')
}

function onNotificationClick(n: { id: string, taskId: string | null }) {
  if (n.taskId) {
    router.push(`/tasks/${encodeURIComponent(n.taskId)}`)
  }
  void markAsRead(n.id)
}

watch(
  [requestedNotificationId, () => notifications.value.length],
  async ([id]) => {
    if (!id) return
    await nextTick()
    const target = document.getElementById(`notification-${id}`)
    target?.scrollIntoView({ block: 'center', behavior: 'smooth' })
    target?.focus({ preventScroll: true })
  },
  { immediate: true },
)

</script>

<template>
  <div class="notifications-page nexus-page nexus-page--reading">
    <div class="page-header nexus-page-header">
      <h1>
        <Bell :size="22" />
        Benachrichtigungen
      </h1>
      <button
        v-if="unreadCount > 0"
        type="button"
        class="mark-all-btn nexus-button"
        :disabled="markingAllRead"
        @click="markAllAsRead()"
      >
        <CheckCheck :size="15" />
        Alle als gelesen markieren
      </button>
    </div>

    <section
      v-if="pendingApprovals.length"
      class="approval-inbox nexus-panel"
      aria-labelledby="approval-inbox-title"
    >
      <header>
        <div>
          <span class="eyebrow">OPENCLAW APPROVALS</span>
          <h2 id="approval-inbox-title">{{ pendingApprovals.length }} privileged actions waiting</h2>
          <p>Review command and plugin approvals in Run Control before execution continues.</p>
        </div>
        <RouterLink class="nexus-button nexus-button--primary" to="/runs">
          <ShieldCheck :size="14" />
          Review queue
        </RouterLink>
      </header>
      <div class="approval-preview">
        <article v-for="approval in pendingApprovals.slice(0, 3)" :key="approval.id">
          <ShieldCheck :size="16" aria-hidden="true" />
          <div>
            <strong>{{ approval.title }}</strong>
            <span>{{ approval.agentId || approval.kind }} · {{ approval.severity }}</span>
          </div>
          <code v-if="approval.command">{{ approval.command }}</code>
        </article>
      </div>
    </section>

    <AsyncStatePanel
      v-if="notificationQuery.isLoading.value && !sortedNotifications.length"
      state="loading"
      title="Benachrichtigungen werden geladen"
    />
    <AsyncStatePanel
      v-else-if="notificationQuery.error.value && !sortedNotifications.length"
      state="error"
      title="Benachrichtigungen nicht verfügbar"
      :problem="notificationQuery.error.value"
      @action="notificationQuery.refetch()"
    />
    <AsyncStatePanel
      v-else-if="sortedNotifications.length === 0"
      state="empty"
      title="Keine Benachrichtigungen"
      message="Neue Aufgaben, Freigaben und Runtime-Ereignisse erscheinen hier."
    />

    <div v-else class="notification-list">
      <div
        v-for="n in sortedNotifications"
        :id="`notification-${n.id}`"
        :key="n.id"
        :class="['notification-card', 'nexus-card', 'nexus-card--interactive', {
          unread: !n.isRead,
          'is-deep-linked': n.id === requestedNotificationId,
        }]"
        role="button"
        tabindex="0"
        :aria-label="`${n.title}${n.isRead ? '' : ', ungelesen'}`"
        @click="onNotificationClick(n)"
        @keydown.enter="onNotificationClick(n)"
        @keydown.space.prevent="onNotificationClick(n)"
      >
        <div class="icon-wrapper" :class="`type-${typeTone(n.type)}`">
          <component :is="typeIcon(n.type)" :size="17" aria-hidden="true" />
        </div>
        <div class="card-body">
          <div :class="['card-title', { bold: !n.isRead }]">{{ n.title }}</div>
          <div v-if="n.message" class="card-message">{{ n.message }}</div>
        </div>
        <div class="card-meta">
          <span class="timestamp">{{ timeAgo(n.createdAt) }}</span>
          <ChevronRight v-if="n.taskId" :size="14" class="arrow" />
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.notifications-page {
  max-width: 720px;
  margin: 0 auto;
  padding: 24px;
}

.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 24px;
  gap: 12px;
}

.page-header h1 {
  margin: 0;
  font-size: 20px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.approval-inbox {
  display: grid;
  gap: 13px;
  padding: 16px;
  border-color: var(--status-queue-line);
  background: linear-gradient(135deg, var(--status-queue-bg), var(--glass));
}

.approval-inbox > header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
}

.approval-inbox h2 {
  margin: 3px 0 5px;
  font-size: 16px;
}

.approval-inbox header p {
  margin: 0;
  color: var(--tx-2);
  line-height: 1.5;
}

.approval-preview {
  display: grid;
  gap: 6px;
}

.approval-preview article {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) minmax(0, 240px);
  align-items: center;
  gap: 10px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--accent-wash);
  color: var(--st-queue);
}

.approval-preview article div {
  display: grid;
  gap: 3px;
}

.approval-preview strong {
  color: var(--tx);
}

.approval-preview span {
  color: var(--tx-3);
  font-family: var(--font-mono-v2);
  font-size: 11px;
}

.approval-preview code {
  overflow: hidden;
  color: var(--tx-2);
  font-family: var(--font-mono-v2);
  font-size: 11px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mark-all-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: transparent;
  color: var(--tx-3);
  font-size: 10.5px;
  cursor: pointer;
  transition: background .15s, color .15s;
}

.mark-all-btn:hover {
  background: var(--nx-accent-soft, color-mix(in srgb, var(--a-mid) 8%, transparent));
  color: var(--tx);
}

/* ── Empty State ── */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 80px 0;
  color: var(--tx-3);
  gap: 16px;
}

.empty-state p {
  font-size: 14px;
  margin: 0;
}

/* ── Notification List ── */
.notification-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.notification-card {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 8px;
  cursor: pointer;
  transition: background .15s;
  border: 1px solid transparent;
}

.notification-card:hover {
  background: var(--nx-accent-soft, color-mix(in srgb, var(--a-mid) 6%, transparent));
}

.notification-card.unread {
  background: color-mix(in srgb, var(--a-blue) 6%, transparent);
  border-color: color-mix(in srgb, var(--a-blue) 12%, transparent);
}

.icon-wrapper {
  width: 36px;
  height: 36px;
  border-radius: 8px;
  display: grid;
  place-items: center;
  flex-shrink: 0;
}

.type-icon {
  font-size: 16px;
  line-height: 1;
}

.card-body {
  flex: 1;
  min-width: 0;
}

.card-title {
  font-size: 12.5px;
  color: var(--tx);
  line-height: 1.4;
}

.card-title.bold {
  font-weight: 700;
  color: var(--tx);
}

.card-message {
  font-size: 10.5px;
  color: var(--tx-3);
  margin-top: 3px;
  line-height: 1.3;
}

.card-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  flex-shrink: 0;
  min-width: 60px;
}

.timestamp {
  font-size: 9px;
  color: var(--tx-3);
  white-space: nowrap;
}

.arrow {
  color: var(--tx-3);
  opacity: .5;
}

.notification-card.is-deep-linked {
  border-color: color-mix(in srgb, var(--a-blue) 48%, var(--line));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--a-blue) 12%, transparent);
}

.spin {
  animation: spin 1s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

@media (max-width: 620px) {
  .approval-inbox > header {
    flex-direction: column;
  }

  .approval-preview article {
    grid-template-columns: auto minmax(0, 1fr);
  }

  .approval-preview code {
    grid-column: 2;
  }
}
</style>
