<template>
  <div>
    <div class="no-print">
      <div class="controls">
        <h3>Batch Print USB Barcode Labels</h3>
        <p>Select USB devices to print (72 labels per page - 6 ULINE labels x 12 mini-labels each, cut after printing):</p>

        <div v-if="loadingDevices" class="loading-msg">Loading USB devices...</div>
        <div v-else-if="devices.length === 0" class="loading-msg">No USB devices found</div>
        <div v-else class="usb-grid">
          <div
            v-for="device in devices"
            :key="device.device_id"
            class="usb-item"
            :class="{ selected: isSelected(device) }"
            @click="toggleDevice(device)"
          >
            <input type="checkbox" :checked="isSelected(device)" @click.stop />
            <label>
              <strong><code>{{ device.device_id || '-' }}</code></strong>
              <div class="alias">{{ device.device_desc || '' }}</div>
            </label>
          </div>
        </div>

        <div class="selected-count">
          Selected: <span class="count">{{ selectedDevices.length }}</span> USB devices
          (<span class="pages">{{ pageCount }}</span> pages)
          <label style="margin-left: 20px;">Start at cell:
            <select v-model="startCell" style="padding: 5px; font-size: 14px;">
              <option value="1">1 - Top Left</option>
              <option value="2">2 - Top Right</option>
              <option value="3">3 - Middle Left</option>
              <option value="4">4 - Middle Right</option>
              <option value="5">5 - Bottom Left</option>
              <option value="6">6 - Bottom Right</option>
            </select>
          </label>
        </div>

        <button class="print-btn" :disabled="selectedDevices.length === 0" @click="print">Print Labels</button>
        <button class="clear-btn" @click="clearSelection">Clear All</button>
        <button class="select-all-btn" @click="selectAll">Select All</button>
      </div>
    </div>

    <div class="sheets-container">
      <div v-for="(page, pageIdx) in sheetPages" :key="pageIdx" class="print-sheet">
        <div class="sheet-label">Page {{ pageIdx + 1 }} of {{ pageCount }}</div>
        <div
          v-for="cellNum in 6"
          :key="cellNum"
          class="label-cell"
          :class="[`cell-${cellNum}`, page[cellNum - 1].hasContent ? 'has-content' : 'empty']"
        >
          <div v-if="page[cellNum - 1].hasContent" class="mini-grid">
            <div
              v-for="(miniItem, miniIdx) in page[cellNum - 1].items"
              :key="miniIdx"
              class="mini-label"
              :class="miniItem ? 'filled' : 'empty'"
            >
              <template v-if="miniItem">
                <img
                  v-if="labelStyle === 'qr'"
                  class="qr-img"
                  :src="qrImages[`${pageIdx}-${cellNum}-${miniIdx}`] || ''"
                />
                <div v-else class="barcode-container">
                  <svg :ref="el => setBarcodeRef(el, pageIdx, cellNum, miniIdx)"></svg>
                </div>
                <div class="serial-text">{{ miniItem.device_id }}</div>
              </template>
            </div>
          </div>
          <div v-else class="empty-cell-text">Empty</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, watch, nextTick } from 'vue'
import { usbApi } from '@/api'
import { barcodeInto, qrPngDataUrl } from '@/utils/codes'
import { getSetting } from '@/utils/siteSettings'
import { buildQrUrl } from '@/utils/qrTarget'

const MINI_LABELS_PER_CELL = 12
const CELLS_PER_PAGE = 6

const devices = ref([])
const selectedDevices = ref([])
const loadingDevices = ref(true)
const startCell = ref('1')
const barcodeRefs = ref({})
// usb_label_style setting: 'barcode' (CODE128 of the serial) or 'qr' (QR code
// linking to the qr_target_usb target, default = the device page).
const labelStyle = ref('barcode')
// QR data-URL images keyed like barcodeRefs. Images print reliably; live
// canvases do not.
const qrImages = ref({})

const pageCount = computed(() => {
  if (selectedDevices.value.length === 0) return 0
  const skippedCells = parseInt(startCell.value) - 1
  const numCells = Math.ceil(selectedDevices.value.length / MINI_LABELS_PER_CELL)
  const totalCellsNeeded = numCells + skippedCells
  return Math.ceil(totalCellsNeeded / CELLS_PER_PAGE)
})

const sheetPages = computed(() => {
  const result = []
  if (selectedDevices.value.length === 0) return result

  const startCellNum = parseInt(startCell.value)
  let usbIdx = 0

  for (let page = 0; page < pageCount.value; page++) {
    const cells = []
    for (let cellNum = 1; cellNum <= CELLS_PER_PAGE; cellNum++) {
      const skipThisCell = page === 0 && cellNum < startCellNum
      const hasContent = !skipThisCell && usbIdx < selectedDevices.value.length

      const items = []
      if (hasContent) {
        for (let mini = 0; mini < MINI_LABELS_PER_CELL; mini++) {
          if (usbIdx < selectedDevices.value.length) {
            items.push(selectedDevices.value[usbIdx])
            usbIdx++
          } else {
            items.push(null)
          }
        }
      }

      cells.push({ hasContent, items })
    }
    result.push(cells)
  }
  return result
})

onMounted(async () => {
  labelStyle.value = (await getSetting('usb_label_style', 'barcode')) === 'qr' ? 'qr' : 'barcode'
  try {
    // listAll: perpage is clamped to 100, and a batch sheet must cover every
    // device, not the first page of them.
    devices.value = await usbApi.listAll()
  } catch (error) {
    console.error('Error loading USB devices:', error)
  } finally {
    loadingDevices.value = false
  }
})

watch([selectedDevices, startCell], async () => {
  await nextTick()
  if (labelStyle.value === 'qr') {
    await generateQrImages()
  } else {
    generateBarcodes()
  }
}, { deep: true })

async function generateQrImages() {
  const next = {}
  for (let pageIdx = 0; pageIdx < sheetPages.value.length; pageIdx++) {
    const page = sheetPages.value[pageIdx]
    for (let cellIdx = 0; cellIdx < page.length; cellIdx++) {
      const cell = page[cellIdx]
      if (!cell.hasContent) continue
      for (let miniIdx = 0; miniIdx < cell.items.length; miniIdx++) {
        const item = cell.items[miniIdx]
        if (!item) continue
        try {
          const url = await buildQrUrl('qr_target_usb', `/usb/${encodeURIComponent(item.device_id)}`, {
            id: item.device_id || '',
            serialnumber: item.device_id || '',
            alias: item.device_desc || '',
          })
          next[`${pageIdx}-${cellIdx + 1}-${miniIdx}`] =
            await qrPngDataUrl(url, { width: 150 })
        } catch (e) {
          console.error('QR error:', item.device_id, e)
        }
      }
    }
  }
  qrImages.value = next
}

function setBarcodeRef(el, pageIdx, cellNum, miniIdx) {
  if (el) {
    barcodeRefs.value[`${pageIdx}-${cellNum}-${miniIdx}`] = el
  }
}

function generateBarcodes() {
  sheetPages.value.forEach((page, pageIdx) => {
    page.forEach((cell, cellIdx) => {
      if (!cell.hasContent) return
      const cellNum = cellIdx + 1
      cell.items.forEach((item, miniIdx) => {
        if (!item) return
        const el = barcodeRefs.value[`${pageIdx}-${cellNum}-${miniIdx}`]
        if (!el) return
        try {
          barcodeInto(el, item.device_id, {
            width: 1, height: 22, background: 'transparent',
          })
        } catch (e) {
          console.error('Barcode error:', item.device_id, e)
        }
      })
    })
  })
}

function isSelected(device) {
  return selectedDevices.value.some(d => d.device_id === device.device_id)
}

function toggleDevice(device) {
  const idx = selectedDevices.value.findIndex(d => d.device_id === device.device_id)
  if (idx > -1) {
    selectedDevices.value.splice(idx, 1)
  } else {
    selectedDevices.value.push(device)
  }
}

function clearSelection() {
  selectedDevices.value = []
}

function selectAll() {
  selectedDevices.value = [...devices.value]
}

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

<style scoped>
@page { size: letter; margin: 0; }

.no-print { margin-bottom: 20px; padding: 20px; }
.controls { background: var(--bg-card); color: var(--text); padding: 20px; border-radius: 8px; margin-bottom: 20px; border: 1px solid var(--border); }
.controls h3 { margin-top: 0; }

.print-btn {
  padding: 10px 30px;
  font-size: 16px;
  cursor: pointer;
  background: var(--primary);
  color: white;
  border: none;
  border-radius: 5px;
  margin-right: 10px;
}
.print-btn:hover:not(:disabled) { background: var(--primary-dark); }
.print-btn:disabled { background: var(--text-light); cursor: not-allowed; }

.clear-btn {
  padding: 10px 20px;
  font-size: 14px;
  cursor: pointer;
  background: var(--danger);
  color: white;
  border: none;
  border-radius: 5px;
  margin-right: 10px;
}

.select-all-btn {
  padding: 10px 20px;
  font-size: 14px;
  cursor: pointer;
  background: var(--success);
  color: white;
  border: none;
  border-radius: 5px;
}

.usb-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 10px;
  max-height: 300px;
  overflow-y: auto;
  border: 1px solid var(--border);
  padding: 10px;
  background: var(--bg);
}

.usb-item {
  display: flex;
  align-items: center;
  padding: 8px;
  background: var(--bg-card);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  cursor: pointer;
}
.usb-item:hover { border-color: var(--primary); }
.usb-item.selected { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary); }
.usb-item input { margin-right: 10px; }
.usb-item label { cursor: pointer; flex: 1; }
.usb-item .alias { font-size: 11px; color: var(--text-light); }

.selected-count { font-weight: bold; margin: 10px 0; color: var(--text); }
.selected-count .count { color: var(--primary); }
.selected-count .pages { color: var(--success); }

.loading-msg { text-align: center; padding: 2rem; color: var(--text-light); }

.sheets-container { display: flex; flex-direction: column; gap: 20px; }

.print-sheet {
  width: 8.5in;
  height: 11in;
  background: white;
  margin: 0 auto;
  position: relative;
  border: 1px solid #ccc;
  page-break-after: always;
}
.print-sheet:last-child { page-break-after: auto; }

.sheet-label { position: absolute; top: -25px; left: 0; font-size: 12px; color: #666; }

.label-cell {
  width: 3in;
  height: 3in;
  position: absolute;
  box-sizing: border-box;
  border: 1px dashed #ccc;
  overflow: hidden;
}
.label-cell.has-content { border: 1px solid var(--primary); }
.label-cell.empty { background: #fafafa; }

.cell-1 { top: 0.875in; left: 1.1875in; }
.cell-2 { top: 0.875in; left: 4.3125in; }
.cell-3 { top: 4in; left: 1.1875in; }
.cell-4 { top: 4in; left: 4.3125in; }
.cell-5 { top: 7.125in; left: 1.1875in; }
.cell-6 { top: 7.125in; left: 4.3125in; }

.mini-grid {
  display: grid;
  grid-template-columns: repeat(3, 1in);
  grid-template-rows: repeat(4, 0.75in);
  width: 3in;
  height: 3in;
}

.mini-label {
  width: 1in;
  height: 0.75in;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  padding: 0.02in;
  border: 1px dotted #ddd;
  overflow: hidden;
}
.mini-label.filled { border: 1px solid #999; }
.mini-label.empty { background: #f8f8f8; border: 1px dotted #eee; }

.barcode-container { text-align: center; line-height: 0; }
.barcode-container svg { max-width: 0.9in; height: 24px; }

.qr-img { width: 0.48in; height: 0.48in; }

.serial-text {
  font-size: 6pt;
  font-weight: bold;
  font-family: monospace;
  text-align: center;
  margin-top: 1px;
  letter-spacing: 0.3px;
}

.empty-cell-text {
  color: #ccc;
  font-size: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
}

@media print {
  /* Force the barcodes/borders to print even when "Background graphics" is
     off. */
  body, .print-sheet, .label-cell, .mini-label, .barcode-container {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
  }
  body { padding: 0; margin: 0; background: white; }
  .no-print { display: none !important; }
  .sheets-container { gap: 0; }
  .print-sheet { border: none; margin: 0; width: 8.5in; height: 11in; overflow: hidden; }
  .sheet-label { display: none; }
  .label-cell { border: none !important; }
  .label-cell.empty { visibility: hidden; }
  .mini-label { border: 1px dotted #ccc !important; }
  .mini-label.empty { visibility: hidden; }
}
</style>
