<template>
  <div>
    <div class="no-print">
      <div class="controls">
        <h3>Print 3D Parts Bin Labels (1in x 0.5in)</h3>
        <p>
          Each label is one page on 1in x 0.5in roll stock: a QR of the gage lab
          tag plus its latest print-file revision (TAG|rev), so a scanned part
          carries which revision it was printed from. Scannable at the parts kiosk.
        </p>

        <div v-if="loading" class="loading-msg">Loading parts...</div>
        <div v-else-if="items.length === 0" class="loading-msg">No parts found</div>
        <div v-else class="parts-grid">
          <div
            v-for="item in items"
            :key="item.printeditemid"
            class="part-item"
            :class="{ selected: isSelected(item) }"
            @click="toggleItem(item)"
          >
            <input type="checkbox" :checked="isSelected(item)" @click.stop />
            <label>
              <strong><code>{{ item.gagelabtag || item.itemcode }}</code></strong>
              <div class="alias">{{ item.itemname }}</div>
            </label>
          </div>
        </div>

        <div class="selected-count">
          Selected: <span class="count">{{ selectedItems.length }}</span> labels
          <label class="copies-label">Copies each:
            <input v-model.number="copies" type="number" min="1" max="10" />
          </label>
        </div>

        <button class="print-btn" :disabled="selectedItems.length === 0"
                @click="print">Print Labels</button>
        <button class="clear-btn" @click="selectedItems = []">Clear All</button>
        <button class="select-all-btn" @click="selectedItems = [...items]">Select All</button>
      </div>
    </div>

    <div class="labels-container">
      <div v-for="(label, index) in printLabels" :key="index" class="bin-label">
        <img v-if="qrDataUrls[index]" :src="qrDataUrls[index]" class="bin-qr" alt="" />
        <div class="bin-code">{{ labelText(label) }}</div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, watch } from 'vue'
import { qrPngDataUrl } from '@/utils/codes'
import { printedpartsApi } from '@/api'

const items = ref([])
const selectedItems = ref([])
const copies = ref(1)
const loading = ref(true)
const qrDataUrls = ref({})

// The QR encodes 'TAG|rev' (gage lab tag, or internal code when untagged, plus
// the latest print-file revision) so a scanned part carries which revision it
// was printed from. Short data keeps the QR low-version and reliable at 0.5in.
function labelTag(item) {
  return item.gagelabtag || item.itemcode
}
function labelPayload(item) {
  return item.latestrevision != null
    ? `${labelTag(item)}|${item.latestrevision}` : labelTag(item)
}
function labelText(item) {
  return item.latestrevision != null
    ? `${labelTag(item)}  rev ${item.latestrevision}` : labelTag(item)
}

onMounted(async () => {
  try {
    // listAll: perpage is clamped to 100, and a label sheet must cover every
    // item, not the first page of them.
    items.value = await printedpartsApi.listAll()
    // ?item=<id> preselects one part (the Detail-page print button)
    const preselect = new URLSearchParams(window.location.search).get('item')
    if (preselect) {
      const match = items.value.find(
        candidate => String(candidate.printeditemid) === preselect)
      if (match) selectedItems.value = [match]
    }
  } catch (error) {
    console.error('Error loading parts:', error)
  } finally {
    loading.value = false
  }
})

const printLabels = computed(() => {
  const labels = []
  for (const item of selectedItems.value) {
    for (let copy = 0; copy < Math.max(1, copies.value); copy++) {
      labels.push(item)
    }
  }
  return labels
})

function isSelected(item) {
  return selectedItems.value.some(
    candidate => candidate.printeditemid === item.printeditemid)
}

function toggleItem(item) {
  if (isSelected(item)) {
    selectedItems.value = selectedItems.value.filter(
      candidate => candidate.printeditemid !== item.printeditemid)
  } else {
    selectedItems.value = [...selectedItems.value, item]
  }
}

watch(printLabels, async labels => {
  const urls = {}
  await Promise.all(labels.map(async (label, index) => {
    // margin 2 = quiet zone (scannability); EC 'M' keeps modules big for the
    // short payload on tiny media; no logo overlay on a 0.36in code.
    urls[index] = await qrPngDataUrl(labelPayload(label), { margin: 2, width: 160 })
  }))
  qrDataUrls.value = urls
}, { deep: true, immediate: true })

function print() {
  window.print()
}
</script>

<style scoped>
.controls {
  max-width: 46rem;
  margin: 1rem auto;
  padding: 1rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 0.5rem;
}
.parts-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 0.5rem;
  max-height: 20rem;
  overflow-y: auto;
  margin: 1rem 0;
}
.part-item {
  display: flex;
  gap: 0.5rem;
  padding: 0.5rem;
  border: 1px solid var(--border);
  border-radius: 0.35rem;
  cursor: pointer;
}
.part-item.selected { border-color: var(--primary); }
.alias { color: var(--text-light); font-size: 0.85rem; }
.selected-count { margin: 0.75rem 0; }
.copies-label { margin-left: 1.25rem; }
.copies-label input { width: 4rem; padding: 0.25rem; }
.print-btn, .clear-btn, .select-all-btn {
  margin-right: 0.5rem;
  padding: 0.5rem 1rem;
  cursor: pointer;
}
.loading-msg { color: var(--text-light); padding: 1rem; }

/* screen preview of the labels */
.labels-container { display: flex; flex-wrap: wrap; gap: 0.4rem; padding: 1rem; }
.bin-label {
  width: 1in;
  height: 0.5in;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: #fff;
  outline: 1px dashed #bbb;
}
/* Square QR sized to leave room for the text line; pixelated keeps the
   modules crisp (no blur) when the data-URL image scales, so it scans. */
.bin-qr { width: 0.36in; height: 0.36in; image-rendering: pixelated; }
.bin-code {
  font-size: 6.5pt;
  font-family: monospace;
  color: #000;
  line-height: 1;
}

/* 1in x 0.5in roll stock: one label per page */
@media print {
  .no-print { display: none; }
  .labels-container { display: block; padding: 0; gap: 0; }
  .bin-label {
    outline: none;
    page-break-after: always;
    break-after: page;
  }
}
</style>

<style>
@media print {
  @page { size: 1in 0.5in; margin: 0; }
  body { margin: 0; }
}
</style>
