<template>
  <div class="spam-wall">
    <div class="header">
      <span class="h-from">FROM</span>
      <span></span>
      <span class="h-subject">SUBJECT</span>
      <span class="h-cost">REPUTATION</span>
    </div>
    <div
      v-for="(item, i) in items"
      :key="i"
      class="row"
      :class="{
        stamped: stampedSet.has(i),
        struck: struckSet.has(i),
        passed: passedSet.has(i),
      }"
    >
      <span class="from">{{ item.from }}</span>
      <span class="sep">&rarr;</span>
      <span class="subject">{{ item.subject }}</span>
      <span class="stamp" :class="{ 'stamp-pass': item.pass }">
        <span class="score">REP {{ item.rep }}</span>
        <span class="verdict">{{ item.pass ? 'PASS' : 'BLOCKED' }}</span>
      </span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, watch, onBeforeUnmount } from 'vue'
import { useIsSlideActive } from '@slidev/client'

const props = withDefaults(defineProps<{
  stage?: number
}>(), {
  stage: 0,
})

const items = [
  { from: 'spam[a3]@***',  subject: 'V*agra $99 — limited offer',            rep: '02', pass: false },
  { from: 'mail[7c]@***',  subject: 'NIGERIAN PRINCE · $25M inheritance',    rep: '05', pass: false },
  { from: 'noreply@***',   subject: 'URGENT: account verification required', rep: '00', pass: false },
  { from: 'mom@gmail.com', subject: 'Re: dinner sunday?',                    rep: '94', pass: true  },
  { from: 'win[8b]@***',   subject: 'FREE iPhone — claim by midnight',       rep: '07', pass: false },
  { from: 'shop[1d]@***',  subject: 'Cheap Rolex replica $25',               rep: '03', pass: false },
]

const stampedSet = ref(new Set<number>())
const struckSet = ref(new Set<number>())
const passedSet = ref(new Set<number>())
let timers: ReturnType<typeof setTimeout>[] = []

function clearTimers() {
  timers.forEach(t => clearTimeout(t))
  timers = []
}

function runStamps() {
  items.forEach((_, i) => {
    timers.push(setTimeout(() => {
      const next = new Set(stampedSet.value)
      next.add(i)
      stampedSet.value = next
    }, i * 280))
  })
}

function runVerdicts() {
  items.forEach((item, i) => {
    timers.push(setTimeout(() => {
      if (item.pass) {
        const next = new Set(passedSet.value)
        next.add(i)
        passedSet.value = next
      } else {
        const next = new Set(struckSet.value)
        next.add(i)
        struckSet.value = next
      }
    }, i * 280))
  })
}

// Snap to a target state without animating (used on backtrack and slide re-entry).
function snapTo(stage: number) {
  clearTimers()
  stampedSet.value = stage >= 1 ? new Set(items.map((_, i) => i)) : new Set()
  if (stage >= 2) {
    struckSet.value = new Set(items.map((_, i) => i).filter(i => !items[i].pass))
    passedSet.value = new Set(items.map((_, i) => i).filter(i => items[i].pass))
  } else {
    struckSet.value = new Set()
    passedSet.value = new Set()
  }
}

watch(() => props.stage ?? 0, (newStage, oldStage = 0) => {
  if (newStage > oldStage) {
    // Forward — animate the new step(s).
    if (newStage >= 1 && oldStage < 1) runStamps()
    if (newStage >= 2 && oldStage < 2) runVerdicts()
  } else if (newStage < oldStage) {
    // Backward — snap to state, no animation.
    snapTo(newStage)
  }
})

const isActive = useIsSlideActive()
watch(isActive, (active) => {
  if (!active) {
    clearTimers()
    stampedSet.value = new Set()
    struckSet.value = new Set()
    passedSet.value = new Set()
  } else {
    snapTo(props.stage ?? 0)
  }
}, { immediate: true })

onBeforeUnmount(clearTimers)
</script>

<style scoped>
.spam-wall {
  display: flex;
  flex-direction: column;
  gap: 0.32rem;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.65rem;
  margin: 0 auto;
  width: 38rem;
}

.header {
  display: grid;
  grid-template-columns: 7.5rem 0.8rem 1fr 3.6rem;
  align-items: center;
  gap: 0.55rem;
  font-family: 'Inter', system-ui, sans-serif;
  font-size: 0.48rem;
  font-weight: 500;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.4);
  padding-bottom: 0.3rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  margin-bottom: 0.15rem;
}
.h-from { text-align: right; }
.h-subject { text-align: left; }
.h-cost { text-align: center; }

.row {
  display: grid;
  grid-template-columns: 7.5rem 0.8rem 1fr 3.6rem;
  align-items: center;
  gap: 0.55rem;
  color: #ff5a5a;
  text-shadow: 0 0 10px rgba(255, 90, 90, 0.2);
  transition: color 0.55s ease, text-shadow 0.55s ease;
}
.row.struck {
  color: rgba(255, 255, 255, 0.42);
  text-shadow: none;
}
.row.passed {
  color: #ffffff;
  text-shadow: 0 0 10px rgba(255, 255, 255, 0.25);
}

.row .from {
  text-align: right;
  font-size: 0.56rem;
  letter-spacing: 0.04em;
  color: rgba(255, 100, 100, 0.55);
  transition: color 0.55s ease;
}
.row.struck .from { color: rgba(255, 255, 255, 0.3); }
.row.passed .from { color: rgba(255, 255, 255, 0.75); }

.row .sep {
  color: rgba(255, 255, 255, 0.3);
  font-family: 'Inter', system-ui, sans-serif;
  text-align: center;
}

.row .subject {
  position: relative;
  letter-spacing: -0.005em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.row .subject::after {
  content: '';
  position: absolute;
  left: 0;
  top: 52%;
  height: 1.5px;
  width: 0;
  background: #ffffff;
  transform: translateY(-50%);
  box-shadow: 0 0 6px rgba(255, 255, 255, 0.6);
  transition: width 0.45s cubic-bezier(.45,.05,.5,.95);
}
.row.struck .subject::after { width: 100%; }

/* Stamp — arrives first, carries the verdict */
.row .stamp {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0.18rem 0.3rem;
  border: 1px solid rgba(255, 255, 255, 0.72);
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.06);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  line-height: 1;
  opacity: 0;
  transform: scale(0.55) rotate(-7deg);
  transition:
    opacity 0.18s ease,
    transform 0.28s cubic-bezier(.2,.7,.3,1.55),
    box-shadow 0.4s ease;
  box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);
}
.row.stamped .stamp {
  opacity: 1;
  transform: scale(1) rotate(-3deg);
  box-shadow: 0 0 14px rgba(255, 255, 255, 0.3);
}
.row .stamp.stamp-pass {
  border-color: rgba(255, 255, 255, 0.95);
  background: rgba(255, 255, 255, 0.14);
}
.row.stamped .stamp.stamp-pass {
  box-shadow: 0 0 18px rgba(255, 255, 255, 0.5);
  transform: scale(1) rotate(2deg);
}

.row .score {
  color: #ffffff;
  font-size: 0.55rem;
  font-weight: 600;
  letter-spacing: 0.04em;
}
.row .verdict {
  color: rgba(255, 255, 255, 0.62);
  font-size: 0.34rem;
  letter-spacing: 0.22em;
  font-family: 'Inter', system-ui, sans-serif;
  text-transform: uppercase;
  margin-top: 0.08rem;
}
.row .stamp.stamp-pass .verdict {
  color: #ffffff;
}
</style>
