<template>
  <span class="inline-block px-4 py-1.5 rounded-full bg-gradient-to-br from-accent to-accent2 text-white text-[15px] font-semibold mb-3">订单已完成</span>

  <div v-if="deliveredCodes.length" class="relative w-full max-w-[min(96vw,980px)] mx-auto my-6 sm:my-7">
    <div ref="deliveredCardRef" class="delivered-shell flex-1 min-w-0 rounded-[var(--shell-radius)] p-[var(--shell-border-width)]">
      <textarea
        class="delivered-textarea w-full min-h-[min(54vh,420px)] sm:min-h-[360px] px-5 py-5 sm:px-6 sm:py-6 rounded-[calc(var(--shell-radius)-var(--shell-border-width))] bg-white/92 text-apptext text-[15px] sm:text-base leading-[1.75] resize-y shadow-[inset_0_1px_0_rgba(255,255,255,0.72)]"
        style="font-family: var(--font-serif);"
        readonly
        :value="deliveredCodes.join('\n')"
      ></textarea>
    </div>
  </div>

  <div v-else-if="isManualDelivery" class="flex items-start gap-3 p-4 bg-[rgba(90,180,120,0.08)] border border-[rgba(90,180,120,0.25)] rounded-lg text-apptext max-w-lg mx-auto text-left">
    <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
    <div>
      <p class="text-base font-semibold text-[#3a9a68] mb-1">等待发货中</p>
      <p class="tag">管理员将尽快处理您的订单并进行发货，请关注您的邮箱或联系方式。</p>
    </div>
  </div>
  <p class="tag mt-3">感谢购买！如有问题请联系售后邮箱。</p>
</template>

<script setup>
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue'

const props = defineProps({
  deliveredCodes: { type: Array, default: () => [] },
  isManualDelivery: { type: Boolean, default: false }
})

const deliveredCardRef = ref(null)

/** 亮暖色粒子，与流光边框统一 */
const FIREWORK_COLORS = [
  '#ff8fa3',
  '#ffb180',
  '#ffe680',
  '#a8f0a5',
  '#8ee8f5',
  '#9db7ff',
  '#d8a7ff'
]

let fireworksCleanup = null

function prefersReducedMotion() {
  return typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches
}

function startCanvasFireworks() {
  if (prefersReducedMotion() || typeof document === 'undefined') return

  const target = deliveredCardRef.value
  if (!target) return

  const canvas = document.createElement('canvas')
  const ctx = canvas.getContext('2d')
  if (!ctx) return

  canvas.style.position = 'fixed'
  canvas.style.left = '0'
  canvas.style.top = '0'
  canvas.style.width = '100%'
  canvas.style.height = '100%'
  canvas.style.zIndex = '9999'
  canvas.style.pointerEvents = 'none'
  document.body.appendChild(canvas)

  let width = 0
  let height = 0
  let cardRect = null
  const devicePixelRatio = Math.min(window.devicePixelRatio || 1, 2)
  const particles = []
  let isRunning = true
  let rafId = 0

  function resize() {
    width = window.innerWidth
    height = window.innerHeight
    canvas.width = Math.floor(width * devicePixelRatio)
    canvas.height = Math.floor(height * devicePixelRatio)
    ctx.setTransform(devicePixelRatio, 0, 0, devicePixelRatio, 0, 0)
    cardRect = target.getBoundingClientRect()
  }

  window.addEventListener('resize', resize)
  resize()

  class Particle {
    constructor(x, y, color) {
      this.x = x
      this.y = y
      this.color = color
      const angle = Math.random() * Math.PI * 2
      const force = Math.pow(Math.random(), 2) * 7 + 1.8
      this.vx = Math.cos(angle) * force
      this.vy = Math.sin(angle) * force
      this.radius = Math.random() * 2.4 + 1.1
      this.alpha = 1
      this.decay = Math.random() * 0.018 + 0.014
      this.gravity = 0.045
      this.friction = 0.95
      this.history = []
      for (let i = 0; i < 6; i++) this.history.push({ x, y })
    }

    update() {
      this.history.shift()
      this.history.push({ x: this.x, y: this.y })
      this.vx *= this.friction
      this.vy *= this.friction
      this.vy += this.gravity
      this.x += this.vx
      this.y += this.vy
      this.alpha -= this.decay
    }

    draw() {
      ctx.shadowColor = this.color
      ctx.shadowBlur = 10
      ctx.beginPath()
      ctx.moveTo(this.history[0].x, this.history[0].y)
      for (let i = 1; i < this.history.length; i++) {
        ctx.lineTo(this.history[i].x, this.history[i].y)
      }
      ctx.strokeStyle = this.color
      ctx.lineWidth = this.radius
      ctx.lineCap = 'round'
      ctx.globalAlpha = this.alpha
      ctx.stroke()
      ctx.globalAlpha = 1
      ctx.shadowBlur = 0
    }
  }

  function createFirework(x, y) {
    if (!isRunning) return
    const color = FIREWORK_COLORS[Math.floor(Math.random() * FIREWORK_COLORS.length)]
    for (let i = 0; i < 72; i++) {
      particles.push(new Particle(x, y, color))
    }
  }

  function createCardFirework() {
    if (!cardRect) return
    const insetX = Math.min(54, cardRect.width * 0.08)
    const insetY = Math.min(46, cardRect.height * 0.12)
    const x = cardRect.left + insetX + Math.random() * Math.max(1, cardRect.width - insetX * 2)
    const y = cardRect.top + insetY + Math.random() * Math.max(1, cardRect.height - insetY * 2)
    createFirework(x, y)
  }

  function loop() {
    if (isRunning) cardRect = target.getBoundingClientRect()
    ctx.clearRect(0, 0, width, height)
    for (let i = particles.length - 1; i >= 0; i--) {
      const p = particles[i]
      p.update()
      if (p.alpha <= 0) particles.splice(i, 1)
      else p.draw()
    }
    if (!isRunning && particles.length === 0) {
      window.clearTimeout(stopSpawningTimer)
      teardown()
      fireworksCleanup = null
      return
    }
    rafId = requestAnimationFrame(loop)
  }

  function teardown() {
    window.removeEventListener('resize', resize)
    window.removeEventListener('mousedown', onPointerDown)
    cancelAnimationFrame(rafId)
    if (canvas.parentNode) canvas.parentNode.removeChild(canvas)
  }

  const stopSpawningTimer = window.setTimeout(() => {
    isRunning = false
  }, 1400)

  function scheduleAuto() {
    if (!isRunning) return
    createCardFirework()
    window.setTimeout(scheduleAuto, Math.random() * 180 + 140)
  }

  const onPointerDown = (e) => {
    if (!isRunning || !cardRect) return
    const isInsideCard =
      e.clientX >= cardRect.left &&
      e.clientX <= cardRect.right &&
      e.clientY >= cardRect.top &&
      e.clientY <= cardRect.bottom
    if (isInsideCard) createFirework(e.clientX, e.clientY)
  }
  window.addEventListener('mousedown', onPointerDown)

  loop()
  for (let i = 0; i < 5; i++) createCardFirework()
  scheduleAuto()

  fireworksCleanup = () => {
    window.clearTimeout(stopSpawningTimer)
    isRunning = false
    teardown()
    fireworksCleanup = null
  }
}

function tryStartFireworks() {
  if (!props.deliveredCodes?.length) return
  if (fireworksCleanup) fireworksCleanup()
  nextTick(startCanvasFireworks)
}

onMounted(() => {
  tryStartFireworks()
})

watch(
  () => props.deliveredCodes.length,
  (n) => {
    if (n) tryStartFireworks()
  }
)

onUnmounted(() => {
  fireworksCleanup?.()
})
</script>

<style scoped>
.delivered-shell {
  --shell-radius: 1.05rem;
  --shell-border-width: 5px;
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background:
    linear-gradient(rgba(255, 255, 255, 0), rgba(255, 255, 255, 0)) padding-box,
    conic-gradient(
      from var(--border-angle),
      #ff8fa3 0deg,
      #ffb180 50deg,
      #ffe680 100deg,
      #a8f0a5 150deg,
      #8ee8f5 205deg,
      #9db7ff 260deg,
      #d8a7ff 315deg,
      #ff8fa3 360deg
    ) border-box;
  border: var(--shell-border-width) solid transparent;
  padding: 0;
  animation: warm-border-spin 3.4s linear infinite;
  box-shadow:
    0 18px 48px rgba(255, 143, 163, 0.2),
    0 8px 22px rgba(255, 230, 128, 0.18),
    0 0 24px rgba(142, 232, 245, 0.16);
}

@property --border-angle {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}

@keyframes warm-border-spin {
  0% {
    --border-angle: 0deg;
  }
  100% {
    --border-angle: 360deg;
  }
}

@media (prefers-reduced-motion: reduce) {
  .delivered-shell {
    animation: none;
  }
}
</style>
