<template>
  <div>
    <!-- Controls (never printed) -->
    <div class="no-print">
      <div class="controls">
        <h3>Batch Print {{ config ? config.label : 'Asset' }} Labels</h3>
        <p v-if="!config" class="error-msg">Unknown asset type.</p>
        <template v-else>
          <div class="control-row">
            <label>Format
              <select v-model="format">
                <option value="uline6">ULINE 6-up (3 in x 3 in, 6 per page)</option>
                <option value="mini72">Mini 72-up (12 per cell, 72 per page)</option>
              </select>
            </label>
            <label>Code type
              <select v-model="codetype">
                <option value="qr">QR code</option>
                <option value="barcode">Barcode (CODE128)</option>
              </select>
            </label>
            <label>Encodes
              <select v-model="encodes">
                <option value="assetpage">Asset page (link)</option>
                <option value="assetnumber">Asset number</option>
                <option value="serialnumber">Serial number</option>
                <option v-if="hasLocation" value="location">Inspection location code</option>
                <option value="custom">Custom target (settings template)</option>
              </select>
            </label>
            <label>Start at cell
              <select v-model="startCell">
                <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>

          <div v-if="loadingAssets" class="loading-msg">Loading assets...</div>
          <div v-else-if="assets.length === 0" class="loading-msg">No assets found.</div>
          <div v-else class="asset-grid">
            <div
              v-for="asset in assets"
              :key="asset.assetid"
              class="asset-item"
              :class="{ selected: isSelected(asset) }"
              @click="toggle(asset)"
            >
              <input type="checkbox" :checked="isSelected(asset)" @click.stop />
              <label>
                <strong>{{ asset.assetnumber || '-' }}</strong>
                <div class="asset-sub">{{ asset.name || '' }}</div>
              </label>
            </div>
          </div>

          <div class="selected-count">
            Selected: <span class="count">{{ selected.length }}</span>
            (<span class="pages">{{ pageCount }}</span> page{{ pageCount === 1 ? '' : 's' }})
          </div>

          <button class="print-btn" :disabled="selected.length === 0" @click="print">Print Labels</button>
          <button class="secondary-btn" @click="selectAll">Select All</button>
          <button class="secondary-btn" @click="clearSelection">Clear</button>
        </template>
      </div>
    </div>

    <!-- Printable sheets -->
    <div class="sheets-container">
      <!-- ULINE 6-up: one asset per 3in cell -->
      <template v-if="format === 'uline6'">
        <div v-for="(page, pageIdx) in uline6Pages" :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"
            :class="[`pos-${cellNum}`, page[cellNum - 1] ? 'active' : 'inactive']"
          >
            <template v-if="page[cellNum - 1]">
              <div class="model-name">{{ titleFor(page[cellNum - 1]) }}</div>
              <div class="qr-container">
                <img
                  v-if="codetype === 'qr'"
                  class="qr-img"
                  :src="qrMap[page[cellNum - 1].assetid] || ''"
                />
                <svg
                  v-else
                  :ref="el => setBarcodeRef(el, page[cellNum - 1].assetid, 'u')"
                  class="barcode-svg"
                ></svg>
              </div>
              <div class="info-section">
                <div class="csf-name">{{ captionMap[page[cellNum - 1].assetid] }}</div>
                <div v-if="page[cellNum - 1].name" class="info-row">{{ page[cellNum - 1].name }}</div>
              </div>
            </template>
          </div>
        </div>
      </template>

      <!-- Mini 72-up: 6 cells x 12 mini labels -->
      <template v-else>
        <div v-for="(page, pageIdx) in mini72Pages" :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="(item, miniIdx) in page[cellNum - 1].items"
                :key="miniIdx"
                class="mini-label"
                :class="item ? 'filled' : 'empty'"
              >
                <template v-if="item">
                  <img v-if="codetype === 'qr'" class="mini-qr" :src="qrMap[item.assetid] || ''" />
                  <svg v-else :ref="el => setBarcodeRef(el, item.assetid, 'm')" class="mini-barcode"></svg>
                  <div class="serial-text">{{ captionMap[item.assetid] }}</div>
                </template>
              </div>
            </div>
            <div v-else class="empty-cell-text">Empty</div>
          </div>
        </div>
      </template>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, watch, nextTick } from 'vue'
import { useRoute } from 'vue-router'
import { renderQrDataUrl, barcodeInto } from '@/utils/codes'
import { getSetting } from '@/utils/siteSettings'
import {
  TYPE_CONFIG, hasLocationType, resolveDefaultEncodes,
  resolveCodeText, captionFor,
} from './assetLabel'

const MINI_PER_CELL = 12
const CELLS_PER_PAGE = 6

const route = useRoute()
const assettype = route.params.assettype
const config = TYPE_CONFIG[assettype] || null

const assets = ref([])
const selected = ref([])
const loadingAssets = ref(true)
const format = ref('uline6')
const codetype = ref('qr')
const encodes = ref('assetpage')
const startCell = ref('1')

// assetid -> encoded code text / caption / QR data URL. Barcodes render to refs.
const codeMap = ref({})
const captionMap = ref({})
const qrMap = ref({})
const barcodeRefs = ref({})

const hasLocation = computed(() => hasLocationType(assettype))

function isSelected(asset) {
  return selected.value.some(a => a.assetid === asset.assetid)
}
function toggle(asset) {
  const idx = selected.value.findIndex(a => a.assetid === asset.assetid)
  if (idx > -1) selected.value.splice(idx, 1)
  else selected.value.push(asset)
}
function selectAll() { selected.value = [...assets.value] }
function clearSelection() { selected.value = [] }

function titleFor(asset) {
  return asset.name || (config ? config.label : 'Asset')
}

const pageCount = computed(() => {
  if (selected.value.length === 0) return 0
  const skipped = parseInt(startCell.value) - 1
  if (format.value === 'uline6') {
    return Math.ceil((selected.value.length + skipped) / CELLS_PER_PAGE)
  }
  const cells = Math.ceil(selected.value.length / MINI_PER_CELL)
  return Math.ceil((cells + skipped) / CELLS_PER_PAGE)
})

// ULINE 6-up: each page is 6 cells, each holding one asset (or null).
const uline6Pages = computed(() => {
  const pages = []
  if (selected.value.length === 0) return pages
  const skip = parseInt(startCell.value) - 1
  let idx = 0
  for (let page = 0; page < pageCount.value; page++) {
    const cells = []
    for (let cell = 0; cell < CELLS_PER_PAGE; cell++) {
      const blank = page === 0 && cell < skip
      cells.push((!blank && idx < selected.value.length) ? selected.value[idx++] : null)
    }
    pages.push(cells)
  }
  return pages
})

// Mini 72-up: each page is 6 cells, each holding up to 12 mini labels.
const mini72Pages = computed(() => {
  const pages = []
  if (selected.value.length === 0) return pages
  const skip = parseInt(startCell.value) - 1
  let idx = 0
  for (let page = 0; page < pageCount.value; page++) {
    const cells = []
    for (let cell = 0; cell < CELLS_PER_PAGE; cell++) {
      const blank = (page === 0 && cell < skip) || idx >= selected.value.length
      const items = []
      if (!blank) {
        for (let mini = 0; mini < MINI_PER_CELL; mini++) {
          items.push(idx < selected.value.length ? selected.value[idx++] : null)
        }
      }
      cells.push({ hasContent: !blank, items })
    }
    pages.push(cells)
  }
  return pages
})

function setBarcodeRef(el, assetid, prefix) {
  if (el) barcodeRefs.value[`${prefix}-${assetid}`] = el
}

// Resolve the encode text + caption for every loaded asset once, then per
// encode-mode change. Kept over the whole list (cheap) so selection is instant.
async function buildCodeMap() {
  const codes = {}
  const captions = {}
  for (const asset of assets.value) {
    codes[asset.assetid] = await resolveCodeText(assettype, asset, encodes.value)
    captions[asset.assetid] = captionFor(asset, encodes.value)
  }
  codeMap.value = codes
  captionMap.value = captions
}

async function buildQrMap() {
  if (codetype.value !== 'qr') return
  const images = {}
  for (const asset of selected.value) {
    const text = codeMap.value[asset.assetid]
    if (text) images[asset.assetid] = await renderQrDataUrl(text)
  }
  qrMap.value = images
}

function renderBarcodes() {
  if (codetype.value !== 'barcode') return
  const prefix = format.value === 'uline6' ? 'u' : 'm'
  const height = format.value === 'uline6' ? 60 : 22
  const width = format.value === 'uline6' ? 2 : 1
  for (const asset of selected.value) {
    const el = barcodeRefs.value[`${prefix}-${asset.assetid}`]
    const text = codeMap.value[asset.assetid]
    if (!el || !text) continue
    try {
      barcodeInto(el, text, { width, height, background: 'transparent' })
    } catch (err) {
      console.error('Barcode error:', asset.assetnumber, err)
    }
  }
}

async function refreshCodes() {
  await buildCodeMap()
  await refreshRender()
}

async function refreshRender() {
  await buildQrMap()
  await nextTick()
  renderBarcodes()
}

onMounted(async () => {
  if (!config) { loadingAssets.value = false; return }
  codetype.value = (await getSetting('label_default_codetype', 'qr')) === 'barcode' ? 'barcode' : 'qr'
  encodes.value = await resolveDefaultEncodes(assettype)
  try {
    // listAll, not list: perpage is clamped to 100 server-side, so a batch
    // sheet built from list() silently omitted every asset past the first
    // 100 and printed a short run that looked complete.
    assets.value = await config.api.listAll()
  } catch (err) {
    console.error('Error loading assets:', err)
  } finally {
    loadingAssets.value = false
    await refreshCodes()
  }
})

watch(encodes, refreshCodes)
watch([selected, format, codetype, startCell], refreshRender, { deep: true })

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

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

.no-print { padding: 20px; }
.controls {
  background: var(--bg-card);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 20px;
}
.controls h3 { margin-top: 0; }
.control-row { display: flex; flex-wrap: wrap; gap: 16px; margin-bottom: 16px; }
.control-row label { display: flex; flex-direction: column; font-size: 0.875rem; gap: 4px; }
.control-row select { padding: 6px; font-size: 0.875rem; }

.asset-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 10px;
  max-height: 320px;
  overflow-y: auto;
  border: 1px solid var(--border);
  padding: 10px;
  background: var(--bg);
}
.asset-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;
}
.asset-item:hover { border-color: var(--primary); }
.asset-item.selected { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary); }
.asset-item input { margin-right: 10px; }
.asset-item label { cursor: pointer; flex: 1; }
.asset-item .asset-sub { font-size: 11px; color: var(--text-light); }

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

.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; }
.secondary-btn {
  padding: 10px 20px;
  font-size: 14px;
  cursor: pointer;
  background: var(--secondary);
  color: white;
  border: none;
  border-radius: 5px;
  margin-right: 10px;
}

.loading-msg, .error-msg { text-align: center; padding: 1.5rem; 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; }

/* ULINE 6-up cells */
.label {
  width: 3in;
  height: 3in;
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0.1in;
  box-sizing: border-box;
}
.label.inactive { border: 1px dashed #ccc; }
.label.active { border: 2px solid var(--primary); }
.model-name { font-size: 11pt; font-weight: bold; text-align: center; margin-bottom: 0.1in; color: #000; }
.qr-container { text-align: center; }
.qr-img { width: 144px; height: 144px; display: block; }
.barcode-svg { width: 2.4in; height: 0.8in; }
.info-section { margin-top: 0.1in; display: flex; flex-direction: column; align-items: center; }
.csf-name { font-size: 12pt; font-weight: bold; font-family: monospace; text-align: center; color: #000; }
.info-row { font-size: 9pt; color: #333; margin: 1px 0; text-align: center; }

/* Mini 72-up cells */
.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; }
.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; }
.mini-qr { width: 0.48in; height: 0.48in; }
.mini-barcode { max-width: 0.9in; height: 24px; }
.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%;
}

/* ULINE S-5627 / 6-up 3in label positions on a letter sheet */
.pos-1, .cell-1 { top: 0.875in; left: 1.1875in; }
.pos-2, .cell-2 { top: 0.875in; left: 4.3125in; }
.pos-3, .cell-3 { top: 4in; left: 1.1875in; }
.pos-4, .cell-4 { top: 4in; left: 4.3125in; }
.pos-5, .cell-5 { top: 7.125in; left: 1.1875in; }
.pos-6, .cell-6 { top: 7.125in; left: 4.3125in; }

@media print {
  body, .print-sheet, .label, .label-cell, .mini-label, .qr-img, .mini-qr, .barcode-svg, .mini-barcode {
    -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 { border: none !important; }
  .label.inactive { visibility: hidden; }
  .label-cell { border: none !important; }
  .label-cell.empty { visibility: hidden; }
  .mini-label { border: 1px dotted #ccc !important; }
  .mini-label.empty { visibility: hidden; }
}
</style>
