<script setup lang="ts">
/**
 * Illustration-grade SVG truck for the cross-dock board. Rendered INSIDE the
 * board's <svg> (the board owns the shared <defs> gradients/filters). The
 * vehicle graphics mirror for outbound trucks (they face away from the dock);
 * the label text is drawn unmirrored on top.
 *
 * Footprint: 104 × 64 user units (incl. wheels + ground shadow).
 */
import type { CdOrder } from '~/composables/useCrossdockBoard'

const props = withDefaults(defineProps<{
  order: CdOrder
  lane: 'in' | 'out'
  /** 'planned' | 'arrived' (in) | 'planned' | 'partial' | 'ready' (out) */
  state?: string | null
  selected?: boolean
  dragging?: boolean
  dropTarget?: boolean
  linked?: boolean
}>(), {
  state: null,
  selected: false,
  dragging: false,
  dropTarget: false,
  linked: false
})

const W = 104

const isGreen = computed(() => props.state === 'arrived' || props.state === 'ready')
const boxFill = computed(() => {
  if (isGreen.value) return 'url(#cdGradBoxGreen)'
  return props.lane === 'in' ? 'url(#cdGradBoxIn)' : 'url(#cdGradBoxOut)'
})
const cabFill = computed(() => {
  if (isGreen.value) return '#26593a'
  return props.lane === 'in' ? '#28405c' : '#3a3158'
})

const truncate = (s: string, n: number) => {
  const str = String(s ?? '')
  return str.length > n ? str.slice(0, n - 1) + '…' : str
}
const qtyLabel = computed(() => {
  const q = props.order.totalQty
  const qs = Number.isInteger(q) ? String(q) : q.toFixed(1)
  return `${props.order.lineCount} Pos · ${qs} Stk`
})
</script>

<template>
  <g
    class="cdTruck"
    :class="{
      'cdTruck--dragging': dragging,
      'cdTruck--selected': selected,
      'cdTruck--dropTarget': dropTarget,
      'cdTruck--ready': state === 'ready'
    }"
  >
    <!-- ground shadow -->
    <ellipse class="cdTruck__shadow" cx="52" cy="60.5" rx="45" ry="3.6" />

    <!-- ready pulse ring (outbound, goods arrived) -->
    <rect
      v-if="state === 'ready'"
      class="cdTruck__pulse"
      x="-4" y="-4" width="112" height="66" rx="10"
      fill="none"
    />

    <!-- vehicle (mirrored for outbound so it faces away from the dock) -->
    <g :transform="lane === 'out' ? `translate(${W},0) scale(-1,1)` : undefined">
      <!-- trailer -->
      <g filter="url(#cdSoftShadow)">
        <rect x="0" y="2" width="70" height="40" rx="3.2" :fill="boxFill" />
        <!-- container panel ribs -->
        <g stroke="rgba(255,255,255,0.10)" stroke-width="1">
          <line x1="10" y1="4" x2="10" y2="40" />
          <line x1="20" y1="4" x2="20" y2="40" />
          <line x1="30" y1="4" x2="30" y2="40" />
          <line x1="40" y1="4" x2="40" y2="40" />
          <line x1="50" y1="4" x2="50" y2="40" />
          <line x1="60" y1="4" x2="60" y2="40" />
        </g>
        <!-- roof highlight + floor rail -->
        <rect x="0" y="2" width="70" height="5" rx="2.5" fill="rgba(255,255,255,0.14)" />
        <rect x="0" y="40" width="70" height="3" fill="rgba(0,0,0,0.28)" />
      </g>

      <!-- chassis between trailer and cab -->
      <rect x="68" y="36" width="10" height="8" fill="#1d2733" />

      <!-- cab -->
      <g filter="url(#cdSoftShadow)">
        <path
          d="M72 16 h16 c3.4 0 6.2 1.6 8 4.4 l5.4 8.4 c1 1.6 1.6 3.4 1.6 5.2 V40 c0 2.2 -1.8 4 -4 4 H72 Z"
          :fill="cabFill"
        />
        <!-- windshield -->
        <path d="M88.5 19.5 c1.8 0.2 3.4 1.2 4.4 2.8 l4.4 7 h-9 z" fill="url(#cdGradGlass)" />
        <!-- door line + handle -->
        <line x1="80" y1="20" x2="80" y2="42" stroke="rgba(0,0,0,0.25)" stroke-width="1" />
        <rect x="82" y="30" width="5" height="1.6" rx="0.8" fill="rgba(255,255,255,0.35)" />
        <!-- headlight + bumper -->
        <rect x="100.5" y="36" width="2.5" height="4" rx="1" fill="#ffd76a" />
        <rect x="94" y="42" width="10" height="3" rx="1.4" fill="#1d2733" />
      </g>

      <!-- exhaust puff while dragging -->
      <g v-if="dragging" class="cdTruck__smoke">
        <circle cx="-4" cy="36" r="2.4" />
        <circle cx="-9" cy="33" r="3.2" />
        <circle cx="-15" cy="30" r="4" />
      </g>

      <!-- wheels -->
      <g class="cdTruck__wheels">
        <g class="cdTruck__wheel">
          <circle cx="16" cy="52" r="7.2" fill="#181d24" />
          <circle cx="16" cy="52" r="3.4" fill="#3d4654" />
          <line x1="16" y1="49" x2="16" y2="55" stroke="#181d24" stroke-width="1.1" />
          <line x1="13" y1="52" x2="19" y2="52" stroke="#181d24" stroke-width="1.1" />
        </g>
        <g class="cdTruck__wheel">
          <circle cx="34" cy="52" r="7.2" fill="#181d24" />
          <circle cx="34" cy="52" r="3.4" fill="#3d4654" />
          <line x1="34" y1="49" x2="34" y2="55" stroke="#181d24" stroke-width="1.1" />
          <line x1="31" y1="52" x2="37" y2="52" stroke="#181d24" stroke-width="1.1" />
        </g>
        <g class="cdTruck__wheel">
          <circle cx="88" cy="52" r="7.2" fill="#181d24" />
          <circle cx="88" cy="52" r="3.4" fill="#3d4654" />
          <line x1="88" y1="49" x2="88" y2="55" stroke="#181d24" stroke-width="1.1" />
          <line x1="85" y1="52" x2="91" y2="52" stroke="#181d24" stroke-width="1.1" />
        </g>
      </g>
    </g>

    <!-- label text (never mirrored) -->
    <g class="cdTruck__label" pointer-events="none">
      <text :x="lane === 'in' ? 5 : 39" y="14" class="cdTruck__doc">{{ truncate(order.documentNo, 12) }}</text>
      <text :x="lane === 'in' ? 5 : 39" y="24" class="cdTruck__partner">{{ truncate(order.partnerName, 15) }}</text>
      <g :transform="lane === 'in' ? 'translate(4,29)' : 'translate(38,29)'">
        <rect x="0" y="0" width="58" height="9.5" rx="4.75" fill="rgba(0,0,0,0.28)" />
        <text x="29" y="7" text-anchor="middle" class="cdTruck__qty">{{ qtyLabel }}</text>
      </g>
    </g>

    <!-- state badge -->
    <g v-if="state === 'arrived' || state === 'ready'" transform="translate(63,-3)">
      <circle r="7" cx="7" cy="7" fill="#22a559" stroke="#ffffff" stroke-width="1.6" />
      <path d="M3.8 7.2 l2.2 2.3 4.2 -4.6" fill="none" stroke="#ffffff" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" />
    </g>
    <g v-else-if="state === 'partial'" transform="translate(63,-3)">
      <circle r="7" cx="7" cy="7" fill="#e8a13c" stroke="#ffffff" stroke-width="1.6" />
      <text x="7" y="10.2" text-anchor="middle" font-size="9" font-weight="700" fill="#ffffff">…</text>
    </g>
    <g v-if="order.isUnfulfillable" :transform="lane === 'in' ? 'translate(-6,-3)' : 'translate(-6,-3)'">
      <path d="M7 0 L14 12 H0 Z" fill="#e8a13c" stroke="#ffffff" stroke-width="1.2" stroke-linejoin="round" />
      <text x="7" y="10.4" text-anchor="middle" font-size="8.5" font-weight="800" fill="#5c3d00">!</text>
    </g>

    <!-- link chip: number of connected orders -->
    <g v-if="linked" transform="translate(-3,44)">
      <circle r="5.5" cx="5.5" cy="5.5" fill="#4a5fc1" stroke="#ffffff" stroke-width="1.2" />
      <path d="M3.4 6.6 a2.4 2.4 0 0 1 0 -3.4 l1 -1 a2.4 2.4 0 0 1 3.4 3.4 M7.6 4.4 a2.4 2.4 0 0 1 0 3.4 l-1 1 a2.4 2.4 0 0 1 -3.4 -3.4"
            fill="none" stroke="#ffffff" stroke-width="1.1" stroke-linecap="round" transform="scale(0.9) translate(1.2,1.2)" />
    </g>

    <!-- drop-target halo -->
    <rect
      v-if="dropTarget"
      class="cdTruck__dropHalo"
      x="-5" y="-6" width="114" height="70" rx="10"
    />

    <!-- selection outline -->
    <rect
      v-if="selected && !dropTarget"
      class="cdTruck__selection"
      x="-3.5" y="-4.5" width="111" height="67" rx="8"
    />
  </g>
</template>

<style scoped>
.cdTruck {
  cursor: grab;
  transition: transform 0.15s ease;
  /* SVG groups transform around the viewport origin by default — anchor
     hover-lift/tilt to the truck itself instead. */
  transform-box: fill-box;
  transform-origin: center;
}
.cdTruck:hover {
  transform: translateY(-2px);
}
.cdTruck--dragging {
  cursor: grabbing;
  transform: translateY(-3px) rotate(-1deg);
}
.cdTruck__shadow {
  fill: rgba(10, 14, 20, 0.22);
  transition: transform 0.15s ease, opacity 0.15s ease;
}
.cdTruck:hover .cdTruck__shadow,
.cdTruck--dragging .cdTruck__shadow {
  transform: scaleX(1.06);
  opacity: 0.75;
}

.cdTruck__doc {
  font-size: 9px;
  font-weight: 700;
  fill: #ffffff;
  letter-spacing: 0.2px;
}
.cdTruck__partner {
  font-size: 7px;
  fill: rgba(255, 255, 255, 0.82);
}
.cdTruck__qty {
  font-size: 6.4px;
  font-weight: 600;
  fill: rgba(255, 255, 255, 0.92);
  letter-spacing: 0.2px;
}

/* wheels spin while the truck is being dragged */
.cdTruck__wheel {
  transform-box: fill-box;
  transform-origin: center;
}
.cdTruck--dragging .cdTruck__wheel {
  animation: cdWheelSpin 0.5s linear infinite;
}
@keyframes cdWheelSpin {
  to { transform: rotate(360deg); }
}

/* exhaust puffs */
.cdTruck__smoke circle {
  fill: rgba(148, 163, 184, 0.4);
  animation: cdSmoke 0.9s ease-out infinite;
}
.cdTruck__smoke circle:nth-child(2) { animation-delay: 0.2s; }
.cdTruck__smoke circle:nth-child(3) { animation-delay: 0.4s; }
@keyframes cdSmoke {
  0% { opacity: 0.7; transform: translate(0, 0) scale(0.7); }
  100% { opacity: 0; transform: translate(-7px, -5px) scale(1.25); }
}

/* outbound "goods arrived — ready" pulse */
.cdTruck__pulse {
  stroke: #22a559;
  stroke-width: 2;
  animation: cdPulse 1.8s ease-out infinite;
}
@keyframes cdPulse {
  0%   { opacity: 0.9; transform: scale(1); }
  70%  { opacity: 0;   transform: scale(1.06); }
  100% { opacity: 0;   transform: scale(1.06); }
}
.cdTruck--ready {
  filter: drop-shadow(0 0 6px rgba(34, 165, 89, 0.55));
}

.cdTruck__dropHalo {
  fill: rgba(74, 95, 193, 0.14);
  stroke: #4a5fc1;
  stroke-width: 2;
  stroke-dasharray: 6 4;
  animation: cdDash 0.6s linear infinite;
}
@keyframes cdDash {
  to { stroke-dashoffset: -10; }
}
.cdTruck__selection {
  fill: none;
  stroke: #4a5fc1;
  stroke-width: 1.8;
  stroke-dasharray: 4 3;
}

@media (prefers-reduced-motion: reduce) {
  .cdTruck,
  .cdTruck__shadow,
  .cdTruck__wheel,
  .cdTruck__smoke circle,
  .cdTruck__pulse,
  .cdTruck__dropHalo {
    animation: none !important;
    transition: none !important;
  }
}
</style>
