<template>
  <div>
    <div class="no-print">
      <div class="controls">
        <h3>Batch Print Printer QR Codes</h3>
        <p>Select printers to print (6 per page):</p>

        <div v-if="loadingPrinters" class="loading-msg">Loading printers...</div>
        <div v-else class="printer-grid">
          <div
            v-for="printer in printers"
            :key="printer.assetid"
            class="printer-item"
            :class="{ selected: isSelected(printer) }"
            @click="togglePrinter(printer)"
          >
            <input type="checkbox" :checked="isSelected(printer)" @click.stop />
            <label>
              <strong>{{ displayName(printer) }}</strong>
              <div class="model">{{ printer.printer?.modelname || '' }}</div>
            </label>
          </div>
        </div>

        <div class="selected-count">
          Selected: <span class="count">{{ selectedPrinters.length }}</span> printers
          (<span class="pages">{{ pageCount }}</span> pages)
        </div>

        <button class="print-btn" :disabled="selectedPrinters.length === 0" @click="print">Print QR Codes</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 pages" :key="pageIdx" class="print-sheet">
        <div class="sheet-label">Page {{ pageIdx + 1 }} of {{ pageCount }}</div>
        <div
          v-for="pos in 6"
          :key="pos"
          class="label"
          :class="[`pos-${pos}`, page[pos - 1] ? 'filled' : 'empty']"
        >
          <template v-if="page[pos - 1]">
            <div class="csf-name">{{ labelName(page[pos - 1]) }}</div>
            <div class="qr-container">
              <img v-if="qrImages[`${pageIdx}-${pos}`]" :src="qrImages[`${pageIdx}-${pos}`]" class="qr-img" alt="QR" />
            </div>
            <div class="info-section">
              <div class="info-inner">
                <div v-if="fqdnFor(page[pos - 1])" class="info-row">{{ fqdnFor(page[pos - 1]) }}</div>
                <div v-if="getIp(page[pos - 1])" class="info-row">{{ getIp(page[pos - 1]) }}</div>
              </div>
            </div>
          </template>
          <span v-else class="empty-label">Empty</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, watch, nextTick } from 'vue'
import { printersApi } from '@/api'
import { renderQrDataUrl } from '@/utils/codes'
import { buildQrUrl } from '@/utils/qrTarget'
import { getPrinterHostnameTemplate } from '@/utils/siteSettings'

const printers = ref([])
const selectedPrinters = ref([])
const loadingPrinters = ref(true)
// QR codes rendered to data-URL images (not live <canvas>): canvases are
// unreliable in print output, images print every time.
const qrImages = ref({})

const pageCount = computed(() => Math.ceil(selectedPrinters.value.length / 6) || 0)

const pages = computed(() => {
  const result = []
  for (let i = 0; i < selectedPrinters.value.length; i += 6) {
    const page = []
    for (let j = 0; j < 6; j++) {
      page.push(selectedPrinters.value[i + j] || null)
    }
    result.push(page)
  }
  return result
})

onMounted(async () => {
  try {
    hostnameTemplate.value = await getPrinterHostnameTemplate()
    // listAll: perpage is clamped to 100, and a batch sheet must cover every
    // printer, not the first page of them.
    printers.value = await printersApi.listAll()
  } catch (error) {
    console.error('Error loading printers:', error)
  } finally {
    loadingPrinters.value = false
  }
})

watch(selectedPrinters, async () => {
  await nextTick()
  generateQRCodes()
}, { deep: true })

async function generateQRCodes() {
  const next = {}
  for (let pageIdx = 0; pageIdx < pages.value.length; pageIdx++) {
    const page = pages.value[pageIdx]
    for (let idx = 0; idx < page.length; idx++) {
      const printer = page[idx]
      if (!printer) continue
      const pos = idx + 1
      const detailId = printer.printer?.printerid || printer.assetid
      const qrUrl = await buildQrUrl('qr_target_printer', `/printers/${detailId}`, {
        printerid: printer.printer?.printerid || '',
        assetid: printer.assetid || '',
        assetnumber: printer.assetnumber || '',
        serialnumber: printer.serialnumber || '',
        ip: getIp(printer) || '',
        hostname: printer.printer?.windowsname || printer.name || '',
      })
      next[`${pageIdx}-${pos}`] = await renderQrDataUrl(qrUrl)
    }
  }
  qrImages.value = next
}

// The printer's FQDN. A stored hostname wins; otherwise the site builds one
// from the IP through the printer_hostname_template setting (ADR-015), which is
// how PrinterForm and the toner report derive it.
const hostnameTemplate = ref('')

function fqdnFor(item) {
  const stored = item?.printer?.hostname
  if (stored) return stored
  const ip = getIp(item)
  if (!ip || !hostnameTemplate.value) return ''
  return hostnameTemplate.value.replace('{ip}', ip.replace(/\./g, '-'))
}

// What goes on the label's prominent top line: the printer's NAME, e.g.
// 8201-HPLaserJetPro. Sites keep that name in different places - the Windows
// queue name when one is set, otherwise the asset's name, and in practice most
// printers carry it as the assetnumber and nothing else, so that is the last
// fallback rather than a blank label. This is a name, not an identifier line:
// the label deliberately carries no separate "Asset #".
function labelName(item) {
  return item?.printer?.windowsname || item?.name || item?.assetnumber || ''
}

function displayName(printer) {
  return printer.assetnumber || printer.name || `Printer-${printer.assetid}`
}

function getIp(printer) {
  // Check direct ipaddress field first (from list API)
  if (printer.ipaddress && printer.ipaddress !== 'USB') return printer.ipaddress
  // Fall back to communications array (from detail API)
  if (!printer.communications?.length) return null
  const primary = printer.communications.find(c => c.isprimary) || printer.communications[0]
  return primary?.ipaddress || primary?.address || null
}

function isSelected(printer) {
  return selectedPrinters.value.some(p => p.assetid === printer.assetid)
}

function togglePrinter(printer) {
  const idx = selectedPrinters.value.findIndex(p => p.assetid === printer.assetid)
  if (idx > -1) {
    selectedPrinters.value.splice(idx, 1)
  } else {
    selectedPrinters.value.push(printer)
  }
}

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

function selectAll() {
  selectedPrinters.value = [...printers.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;
}

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

.printer-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;
}
.printer-item:hover { border-color: var(--primary); }
.printer-item.selected { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary); }
.printer-item input { margin-right: 10px; }
.printer-item label { cursor: pointer; flex: 1; }
.printer-item .model { 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 {
  width: 3in;
  height: 3in;
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0.1in;
  box-sizing: border-box;
  border: 1px dashed #ccc;
}
.label.filled { border: 2px solid var(--primary); }
.label.empty { background: #fafafa; }

.qr-img { width: 144px; height: 144px; display: block; }

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

.model-name { font-size: 11pt; font-weight: bold; text-align: center; margin-bottom: 0.1in; color: #000; }
.qr-container { text-align: center; }
.info-section { margin-top: 0.1in; display: flex; flex-direction: column; align-items: center; }
.info-inner { text-align: left; }
.info-row { font-size: 9pt; color: #333; margin: 1px 0; white-space: nowrap; }
.csf-name { font-size: 12pt; font-weight: bold; font-family: monospace; text-align: center; margin-bottom: 0.06in; color: #000; }
.empty-label { color: #999; font-size: 14px; }

@media print {
  /* Force the browser to print rendered images/colors even when the user's
     "Background graphics" option is off. Without this the QR images and
     borders can drop out of the printout. */
  body, .print-sheet, .label, .qr-img, .qr-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 { border: none !important; }
  .label.empty { visibility: hidden; }
}
</style>
