<script setup lang="ts">
import { computed, ref } from 'vue';
import { useVotingStore, TICKET_INFO } from '../stores/voting';
import { useConnectionStore } from '../stores/connection';
import Postmark from './Postmark.vue';
import stampImage from '../assets/images/stamp-horse-2026.png';
import { GUOCHAO_ICONS } from '../utils/svgIcons';
import type { TicketType } from '@gala/shared/constants';
import type { VoteStamp } from '@gala/shared/types';

interface Props {
  programId: string;
  programName: string;
  teamName?: string;
  coverImage?: string;
  index?: number; // For stagger animation
  status?: 'pending' | 'voting' | 'completed';
  isCurrent?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  index: 0,
  status: 'pending',
  isCurrent: false,
});

const votingStore = useVotingStore();
const connectionStore = useConnectionStore();

// Animation states
const isStamping = ref(false);
const stampPhase = ref<'idle' | 'approach' | 'impact' | 'release'>('idle');
const showInkMark = ref(false);

// Check if this card has a stamp
const stampedWith = computed(() => votingStore.getProgramStamp(props.programId));
const hasStamp = computed(() => stampedWith.value !== null);
const stampInfo = computed(() => {
  if (!stampedWith.value) return null;
  return TICKET_INFO[stampedWith.value];
});

// Can this card receive a stamp (requires voting permission check)
const canVote = computed(() => {
  const check = votingStore.canVoteForProgram(props.programId);
  return check.allowed;
});

const canReceiveStamp = computed(() => {
  return votingStore.isStampSelected && !hasStamp.value && canVote.value;
});

// Get voting status message
const votingStatusLabel = computed(() => {
  switch (props.status) {
    case 'voting': return '投票中';
    case 'completed': return '已结束';
    default: return '待投票';
  }
});

// Stagger delay for entrance animation
const entranceDelay = computed(() => `${props.index * 100}ms`);

async function handleCardClick() {
  if (!votingStore.isStampSelected) return;
  if (hasStamp.value) return;

  isStamping.value = true;

  // Phase 1: Approach (0-100ms)
  stampPhase.value = 'approach';
  await delay(100);

  // Phase 2: Impact (100-150ms)
  stampPhase.value = 'impact';
  if (navigator.vibrate) {
    navigator.vibrate(40); // Sharp tick
  }
  await delay(50);

  // Phase 3: Release (150-300ms)
  stampPhase.value = 'release';
  showInkMark.value = true;

  // Cast vote (optimistic UI)
  await votingStore.castVote(props.programId);

  await delay(150);

  // Reset
  isStamping.value = false;
  stampPhase.value = 'idle';
}

function delay(ms: number): Promise<void> {
  return new Promise(resolve => setTimeout(resolve, ms));
}
</script>

<template>
  <div
    class="postcard"
    :class="{
      'has-stamp': hasStamp,
      'can-stamp': canReceiveStamp,
      'is-stamping': isStamping,
      'is-current': isCurrent,
      'is-disabled': !canVote && !hasStamp,
    }"
    :style="{ '--entrance-delay': entranceDelay }"
    @click="handleCardClick"
  >
    <!-- Status Badge -->
    <div v-if="status !== 'pending'" class="status-badge" :class="status">
      {{ votingStatusLabel }}
    </div>
    <!-- Paper Texture Background -->
    <div class="paper-texture">
      <!-- Left: Cover Image (Picture Side) -->
      <div class="postcard-image">
        <img v-if="coverImage" :src="coverImage" :alt="programName" />
        <div v-else class="image-placeholder">
          <span class="placeholder-text">{{ programName }}</span>
        </div>
      </div>

      <!-- Right: Content Area (Address Side) -->
      <div class="postcard-content">
        <!-- Top: Program Info -->
        <div class="content-header">
          <h3 class="program-title">{{ programName }}</h3>
          <p v-if="teamName" class="team-name">{{ teamName }}</p>
        </div>

        <!-- Middle: Writing Area (Short Quote) -->
        <div class="writing-area">
          <p class="micro-copy handwritten">With all our passion</p>
          <span class="caption">倾情呈现</span>
        </div>

        <!-- Bottom: Address Block -->
        <div class="address-block">
          <div class="address-row">
            <span class="label">From:</span>
            <span class="handwritten">{{ teamName || 'The Performer' }}</span>
            <div class="address-line"></div>
          </div>
          <div class="address-row">
            <span class="label">To:</span>
            <span class="handwritten">The 2026 Company Family</span>
            <div class="address-line"></div>
          </div>
        </div>

        <!-- Stamp Area -->
        <div class="stamp-zone">
          <!-- Real stamp image (always visible) -->
          <img :src="stampImage" alt="邮票" class="stamp-image" />
          
          <!-- Postmark overlay on bottom-left of stamp -->
          <Postmark
            v-if="hasStamp && stampInfo"
            :award-name="stampInfo.name"
            :award-icon-key="stampedWith!"
            :user-name="connectionStore.userName || ''"
            color="gold"
            class="applied-stamp"
          />
        </div>
      </div>
    </div>

    <!-- Stamping Tool Overlay -->
    <Transition name="stamp-tool">
      <div v-if="isStamping && votingStore.selectedStamp" class="stamp-tool-overlay">
        <div
          class="stamp-tool"
          :class="[`phase-${stampPhase}`]"
        >
          <div class="tool-handle">
            <div class="handle-top"></div>
            <div class="handle-body"></div>
          </div>
          <div class="tool-base">
            <div class="base-plate"></div>
            <div class="base-relief" v-html="GUOCHAO_ICONS[votingStore.selectedStamp as keyof typeof GUOCHAO_ICONS]"></div>
          </div>
          
          <!-- Impact Effects: Gold Dust / Particles -->
          <div v-if="stampPhase === 'impact' || stampPhase === 'release'" class="impact-effects">
            <div v-for="i in 12" :key="i" class="gold-dust"></div>
          </div>
        </div>
      </div>
    </Transition>
  </div>
</template>

<style lang="scss" scoped>
@use 'sass:math';
@use 'sass:color';
@use '../assets/styles/variables.scss' as *;

// Paper & Ink colors
$paper-cream: #f8f4e8;
$paper-lines: rgba(180, 160, 140, 0.3);
$ink-blue: #000080;
$ink-red: #c21f30;
$ink-charcoal: #333;

.postcard {
  position: relative;
  border-radius: 4px;
  overflow: hidden;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
  transition: transform 0.2s ease, box-shadow 0.2s ease, opacity 0.3s ease;
  background-color: $paper-cream;

  // Entrance animation
  animation: postcard-enter 0.5s ease-out backwards;
  animation-delay: var(--entrance-delay, 0ms);

  &:active:not(.is-stamping) {
    transform: scale(0.98);
  }

  &.can-stamp {
    box-shadow: 0 4px 20px rgba($color-gold, 0.3), 0 0 0 2px rgba($color-gold, 0.5);
    animation: pulse-glow 1.5s ease-in-out infinite;
  }

  &.has-stamp {
    .paper-texture {
      background-color: color.adjust($paper-cream, $lightness: -2%);
    }
  }

  &.is-current {
    box-shadow: 0 4px 25px rgba($color-gold, 0.4), 0 0 0 3px $color-gold;
  }

  &.is-disabled {
    opacity: 0.6;
    pointer-events: none;
  }
}

// Status Badge
.status-badge {
  position: absolute;
  top: 8px;
  left: 8px;
  padding: 4px 10px;
  border-radius: 4px;
  font-size: 10px;
  font-weight: 600;
  z-index: 5;

  &.voting {
    background: $color-gold;
    color: #000;
    animation: pulse-badge 1.5s ease-in-out infinite;
  }

  &.completed {
    background: rgba(0, 0, 0, 0.5);
    color: #fff;
  }
}

@keyframes pulse-badge {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.7; }
}

.paper-texture {
  display: flex;
  background-color: transparent;
  // Paper grain noise texture
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.06'/%3E%3C/svg%3E");
  min-height: 160px;
}

// Left: Image area
.postcard-image {
  flex: 0 0 40%;
  position: relative;
  overflow: hidden;
  border-right: 1px dashed $paper-lines;

  img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}

.image-placeholder {
  width: 100%;
  height: 100%;
  min-height: 160px;
  background: linear-gradient(135deg, $color-primary 0%, color.adjust($color-primary, $lightness: -10%) 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: $spacing-md;
}

.placeholder-text {
  font-size: $font-size-xl;
  font-weight: bold;
  color: $color-gold;
  text-align: center;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}

// Right: Content area
.postcard-content {
  flex: 1;
  padding: $spacing-md;
  display: flex;
  flex-direction: column;
  position: relative;
}

.content-header {
  margin-bottom: $spacing-xs;
}

.program-title {
  font-size: $font-size-lg;
  font-weight: bold;
  color: #2a2a2a;
  font-family: 'Noto Serif SC', serif;
  margin-bottom: 0;
}

.team-name {
  font-size: 10px;
  color: #888;
  font-family: 'Courier New', monospace;
  margin-bottom: $spacing-xs;
}

// Writing style
.handwritten {
  font-family: 'Ma Shan Zheng', 'Kaiti', 'Brush Script MT', cursive;
  color: $ink-blue;
  display: inline-block;
  transform: rotate(-1deg);
  font-size: $font-size-md;
}

.writing-area {
  margin-bottom: $spacing-sm;
  .micro-copy {
    font-size: $font-size-sm;
    margin-bottom: 2px;
  }
  .caption {
    font-size: 10px;
    color: #999;
    font-style: italic;
  }
}

.address-block {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.address-row {
  position: relative;
  display: flex;
  align-items: flex-end;
  gap: 4px;

  .label {
    font-size: 10px;
    color: #444;
    font-weight: bold;
    min-width: 30px;
  }

  .handwritten {
    flex: 1;
    padding-left: 4px;
    position: relative;
    z-index: 1;
  }
}

.address-line {
  position: absolute;
  bottom: 2px;
  left: 30px;
  right: 0;
  border-bottom: 1px dotted #ccc;
}

// Stamp zone
.stamp-zone {
  position: absolute;
  top: $spacing-sm;
  right: $spacing-sm;
  width: 70px;
  height: 70px;
  display: flex;
  align-items: flex-start;
  justify-content: flex-end;
}

.stamp-image {
  width: 60px;
  height: 60px;
  object-fit: contain;
  border: 1px solid rgba(0, 0, 0, 0.1);
  box-shadow: 1px 1px 3px rgba(0,0,0,0.1);
}

.applied-stamp {
  position: absolute;
  bottom: -5px;
  left: -10px;
  mix-blend-mode: multiply;
  transform: rotate(-8deg);
  z-index: 2;
}

// Stamp Tool Overlay
.stamp-tool-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  z-index: 100;
}

.stamp-tool {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  transition: all 0.15s cubic-bezier(0.18, 0.89, 0.32, 1.28);
}

.tool-handle {
  display: flex;
  flex-direction: column;
  align-items: center;
  filter: drop-shadow(0 4px 8px rgba(0,0,0,0.4));

  .handle-top {
    width: 20px;
    height: 10px;
    background: #4a342e;
    border-radius: 50% / 100% 100% 0 0;
  }

  .handle-body {
    width: 24px;
    height: 45px;
    background: linear-gradient(90deg, #5d4037 0%, #8d6e63 50%, #5d4037 100%);
    border-radius: 2px 2px 4px 4px;
    border: 1px solid rgba(255,255,255,0.1);
  }
}

.tool-base {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: -2px;

  .base-plate {
    width: 54px;
    height: 12px;
    background: linear-gradient(90deg, #aa8a31 0%, #f0c239 50%, #aa8a31 100%);
    border-radius: 4px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.3);
  }

  .base-relief {
    width: 48px;
    height: 48px;
    margin-top: -2px;
    background: $ink-red;
    border-radius: 2px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgba(255,255,255,0.9);
    padding: 8px;
    box-shadow: inset 0 0 10px rgba(0,0,0,0.5);

    :deep(svg) {
      width: 100%;
      height: 100%;
    }
  }
}

// Animation phases
.phase-approach {
  transform: scale(1.4) translateY(-80px) rotate(-10deg);
  opacity: 0.8;
}

.phase-impact {
  transform: scale(0.9) translateY(0) rotate(0);
  opacity: 1;
}

.phase-release {
  transform: scale(1.1) translateY(-100px) rotate(5deg);
  opacity: 0;
}

// Impact Effects: Gold Dust
.impact-effects {
  position: absolute;
  top: 90%;
  left: 50%;
  width: 100px;
  height: 100px;
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: center;
}

.gold-dust {
  position: absolute;
  width: 4px;
  height: 4px;
  background: $color-gold;
  border-radius: 50%;
  filter: blur(1px);
  animation: dust-fly 0.6s ease-out forwards;

  @for $i from 1 through 12 {
    &:nth-child(#{$i}) {
      $angle: $i * 30deg;
      $dist: 40px + random(40);
      --tx: #{math.cos($angle) * $dist};
      --ty: #{math.sin($angle) * $dist};
      animation-delay: random(50) * 1ms;
    }
  }
}

@keyframes dust-fly {
  0% { transform: translate(0, 0) scale(1); opacity: 1; }
  100% { transform: translate(var(--tx), var(--ty)) scale(0); opacity: 0; }
}

// Keyframes
@keyframes postcard-enter {
  from {
    opacity: 0;
    transform: translateY(20px) scale(0.95);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes pulse-glow {
  0%, 100% {
    box-shadow: 0 4px 20px rgba($color-gold, 0.3), 0 0 0 2px rgba($color-gold, 0.3);
  }
  50% {
    box-shadow: 0 4px 30px rgba($color-gold, 0.5), 0 0 0 3px rgba($color-gold, 0.5);
  }
}

// Transition for stamp tool
.stamp-tool-enter-active,
.stamp-tool-leave-active {
  transition: opacity 0.2s;
}

.stamp-tool-enter-from,
.stamp-tool-leave-to {
  opacity: 0;
}
</style>
