<template>
  <Teleport to="body">
    <div class="toast-container">
      <TransitionGroup name="toast" tag="div" class="toast-stack">
        <div
          v-for="item in toastStore.displaying"
          :key="item.id"
          :class="['toast-item', `toast-item--${item.type}`]"
          role="status"
          aria-live="polite"
        >
          <span class="toast-message">
            {{ item.count > 1 ? `${item.message} (×${item.count})` : item.message }}
          </span>
        </div>
      </TransitionGroup>
    </div>
  </Teleport>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue'
import { useToastStore } from '@/stores/toast'
import type { ToastItem } from '@/stores/toast'

const toastStore = useToastStore()
const TIMEOUT_MS = 3000
const timers = new Map<string, ReturnType<typeof setTimeout>>()

function scheduleRemove(item: ToastItem) {
  const t = setTimeout(() => {
    toastStore.remove(item.id)
    timers.delete(item.id)
  }, TIMEOUT_MS)
  timers.set(item.id, t)
}

function syncTimers() {
  for (const item of toastStore.displaying) {
    const existing = timers.get(item.id)
    if (existing) clearTimeout(existing)
    scheduleRemove(item)
  }
  for (const [id] of timers) {
    if (!toastStore.displaying.some((d) => d.id === id)) {
      clearTimeout(timers.get(id)!)
      timers.delete(id)
    }
  }
}

onMounted(() => {
  syncTimers()
  const stop = toastStore.$subscribe(syncTimers)
  onUnmounted(() => {
    stop()
    timers.forEach((t) => clearTimeout(t))
    timers.clear()
  })
})
</script>

<style scoped>
.toast-container {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10000;
  pointer-events: none;
  /* 避开顶部导航栏（约 64px）+ 安全区域 */
  padding: max(72px, calc(64px + env(safe-area-inset-top))) 16px 16px;
  display: flex;
  justify-content: center;
}

.toast-stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: min(520px, calc(100vw - 32px));
}

.toast-item {
  position: relative;
  width: 100%;
  padding: 12px 28px;
  border-radius: 8px;
  backdrop-filter: blur(8px);
  text-align: center;
  font-size: 14px;
  font-weight: 500;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  pointer-events: auto;
}

.toast-item--success {
  background: rgba(76, 175, 80, 0.65);
  color: rgba(255, 255, 255, 0.95);
}

.toast-item--error {
  background: rgba(244, 67, 54, 0.65);
  color: rgba(255, 255, 255, 0.95);
}

.toast-item--warning {
  background: rgba(255, 152, 0, 0.65);
  color: rgba(33, 33, 33, 0.95);
}

.toast-item--info {
  background: rgba(33, 150, 243, 0.65);
  color: rgba(255, 255, 255, 0.95);
}

.toast-message {
  display: block;
  width: 100%;
}

/* Transition */
.toast-enter-active,
.toast-leave-active {
  transition: all 0.25s ease;
}

.toast-enter-from {
  opacity: 0;
  transform: translateY(-12px);
}

.toast-leave-to {
  opacity: 0;
  transform: translateY(-8px);
}

/* 下方 Toast 在上方消失时平缓上移 */
.toast-move {
  transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}
</style>
