<script setup>
import { date } from 'alga-js'
import { SelectBox } from 'tedir-select'
import { toast } from 'bulma-toast'
import DOMPurify from 'dompurify'

// Dynamic imports for client-side only
let jsPDF
let JsBarcode

const config = useRuntimeConfig()

definePageMeta({
  middleware: ['auth', 'org']
})

const warehouses = useCookie('logship_warehouses')
const warehouse = useCookie('logship_warehouse')
const warehouseId = useCookie('logship_warehouse_id')

const form = ref({
  warehouse: warehouse.value?.Name || '',
  warehouseId: warehouseId.value || '',
  locatorType: '',
  locatorTypeId: '',
  x: '',
  y: '',
  z: '',
  labelPrinter: 'labelprinter-2',
  labelPrinterId: 'b'
})

const loading = ref({})
const getOptions = ref({})
const setOptions = async (url, key) => {
  loading.value[key] = true
  const res = await $fetch('/api/'+url, {
    headers: useRequestHeaders(['cookie'])
  })
  if(res) {
    getOptions.value[key] = res

    if(getOptions.value[key]?.records) {
      getOptions.value[key].records.unshift({
        id: '',
        Name: '-- Select Option --',
        ISO_Code: '-- Select Option --',
        Address1: '-- Select Option --'
      })
    }
  }
  loading.value[key] = false
}

const locators = ref([])
const filterLocatorChooser = async () => {
  locators.value = []
  const queries = ['warehouseId', 'locatorTypeId', 'x', 'y', 'z', 'labelPrinterId']
  const defaultUrl = '/api/materials/locators'
  let newUrl = defaultUrl
  for(let query of queries) {
    if(form.value[query]) {
      if(newUrl === defaultUrl) {
        newUrl += `?${query}=${form.value[query]}`
      } else {
        newUrl += `&${query}=${form.value[query]}`
      }
    }
  }
  const res = await $fetch(newUrl)
  if(res) {
    console.log(res)
    locators.value = res?.records || []
  }
}
onMounted(filterLocatorChooser)

const serverSidePrinting = async (content) => {
  const labelPrinters = {
    a: 'labelprinter-1',
    b: 'labelprinter-2',
    c: 'labelprinter-3',
    d: 'labelprinter-4',
    e: 'labelprinter-5',
    f: 'labelprinter-6',
  }
  let labelPrinter = 'labelprinter-2'
  if(labelPrinters[content.labelPrinterId]) {
    labelPrinter = labelPrinters[content.labelPrinterId]
  }
  const res = await $fetch(`/api/print/${labelPrinter}/locator`, {
    method: 'POST',
    body: content
  })
  if(res) {
    if(res?.stdout) {
      toast({
        message: `The labels has been printed via server side printing!`,
        type: 'is-success',
        duration: 2000
      })
    }
  }
}

const generateLabel = (code = '', format = 'CODE128') => {
  if (process.client && JsBarcode) {
    // Create a browser canvas element
    const canvasElem = document.createElement('canvas')
    canvasElem.width = 400
    canvasElem.height = 200

    try {
      JsBarcode(canvasElem, code, {
        format: format,
        lineColor: "#000",
        displayValue: false,
        width: 2,
        height: 100
      })
      return canvasElem.toDataURL()
    } catch (error) {
      console.warn('Barcode generation failed:', error)
      return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=='
    }
  }
  // Return a transparent 1x1 pixel as fallback
  return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=='
}

const labelByPrinter = (doc, no, entry) => {
  if(entry.labelPrinterId === 'a') {
    doc.addPage()
    doc.setPage(no)
    doc.setFontSize(14)
    doc.text('Labelprinter-1', 0, 5)
    doc.text(String((entry?.M_Warehouse_ID?.identifier ?? '') +' - '+ entry.Value), 0, 8)
    doc.setFontSize(14)
    doc.text(String('Locator: '+(entry?.M_Locator_ID?.identifier ?? '')+' | X: '+ entry.X + ' | Y: ' + entry.Y + ' | Z: ' + entry.Z), 0, 17)
    // doc.setFontSize(12)
    // doc.text(`${entry.X ?? 0},${entry.Y ?? 0},${entry.Z ?? 0}`, 4, 46)
    doc.addImage(generateLabel(String(entry.Value ?? '0000')), 'image/png', 9, 20, 60, 28)
  }
  else if (entry.labelPrinterId === 'b') {
    doc.addPage()
    doc.setPage(no)
    doc.setFontSize(18)
    // doc.text('Labelprinter-2', 0, 5)
    doc.text(String(entry.X + ' - ' + entry.Y + ' - ' + entry.Z), 3, 12)
    // doc.setFontSize(14)
    // doc.text(String('Locator: '+(entry?.M_Locator_ID?.identifier ?? '')+' | X: '+ entry.X + ' | Y: ' + entry.Y + ' | Z: ' + entry.Z), 0, 17)
    // doc.setFontSize(12)
    // doc.text(`${entry.X ?? 0},${entry.Y ?? 0},${entry.Z ?? 0}`, 4, 46)
    doc.addImage(generateLabel(String(entry.Value ?? '0000')), 'image/png', 9, 20, 60, 28)
  } else if(entry.labelPrinterId === 'c') {
    doc.addPage()
    doc.setPage(no)
    // doc.rotate(90)
    doc.setFontSize(34)
    doc.text(String(entry.X + ' - ' + entry.Y + ' - ' + entry.Z), 8, 18)
    // doc.setFontSize(12)
    // doc.text(String((entry?.AD_Org_ID?.identifier ?? '')), 4, 10)
    doc.setFontSize(12)
    // doc.text(`${entry.X ?? 0},${entry.Y ?? 0},${entry.Z ?? 0}`, 4, 46)
    doc.addImage(generateLabel(String(entry.Value ?? '0000')), 'image/png', 5, 30, 65, 20)
  } else if(entry.labelPrinterId === 'd') {
    doc.addPage()
    doc.setPage(no)
    doc.setFontSize(14)
    doc.text('Labelprinter-4', 4, 5)
    doc.text(String((entry?.M_Warehouse_ID?.identifier ?? '') +' - '+ entry.Value), 4, 8)
    doc.setFontSize(12)
    doc.text(String((entry?.AD_Org_ID?.identifier ?? '')), 4, 40)
    doc.setFontSize(12)
    // doc.text(`${entry.X ?? 0},${entry.Y ?? 0},${entry.Z ?? 0}`, 4, 46)
    doc.addImage(generateLabel(String(entry.Value ?? '0000')), 'image/png', 30, 25, 40, 26)
  } else if(entry.labelPrinterId === 'e') {
    doc.addPage()
    doc.setPage(no)
    // doc.rotate(90)
    doc.setFontSize(30)
    doc.text(String(entry.X + ' - ' + entry.Y + ' - ' + entry.Z), 8, 20)
    // doc.setFontSize(12)
    // doc.text(String((entry?.AD_Org_ID?.identifier ?? '')), 4, 10)
    doc.setFontSize(12)
    // doc.text(`${entry.X ?? 0},${entry.Y ?? 0},${entry.Z ?? 0}`, 4, 46)
    doc.addImage(generateLabel(String(entry.Value ?? '0000')), 'image/png', 5, 30, 65, 20)
  } else if(entry.labelPrinterId === 'f') {
    doc.addPage()
    doc.setPage(no)
    doc.setFontSize(14)
    doc.text('Labelprinter-6', 4, 5)
    doc.text(String((entry?.M_Warehouse_ID?.identifier ?? '') +' - '+ entry.Value), 4, 8)
    doc.setFontSize(12)
    doc.text(String((entry?.AD_Org_ID?.identifier ?? '')), 4, 40)
    doc.setFontSize(12)
    // doc.text(`${entry.X ?? 0},${entry.Y ?? 0},${entry.Z ?? 0}`, 4, 46)
    doc.addImage(generateLabel(String(entry.Value ?? '0000')), 'image/png', 30, 25, 40, 26)
  } else {
    doc.addPage()
    doc.setPage(no)
    doc.setFontSize(11)
    doc.text('Labelprinter-Unknown', 4, 5)
    doc.text(String((entry?.M_Warehouse_ID?.identifier ?? '') +' - '+ entry.Value), 4, 8)
    doc.setFontSize(12)
    doc.text(String('Locator: '+(entry?.M_Locator_ID?.identifier ?? '')+' | X: '+ entry.X + ' | Y: ' + entry.Y + ' | Z: ' + entry.Z), 4, 17)
    //doc.setFontSize(12)
    //doc.text(`${entry.X ?? 0},${entry.Y ?? 0},${entry.Z ?? 0}`, 4, 46)
    doc.addImage(generateLabel(String(entry.Value ?? '0000')), 'image/png', 9, 20, 60, 28)
  }
}

const printLabels = async (type = 'server') => {
  // Ensure we're on the client side and load dependencies
  if (!process.client) {
    toast({
      message: 'PDF generation is only available on client side!',
      type: 'is-warning',
      duration: 2000
    })
    return
  }

  try {
    // Dynamic import of jsPDF and JsBarcode for client-side only
    if (!jsPDF) {
      const jsPDFModule = await import('jspdf')
      jsPDF = jsPDFModule.jsPDF
    }

    if (!JsBarcode) {
      const JsBarcodeModule = await import('jsbarcode')
      JsBarcode = JsBarcodeModule.default
    }
  } catch (error) {
    console.error('Failed to load PDF/Barcode libraries:', error)
    toast({
      message: 'Failed to load required libraries for PDF generation!',
      type: 'is-danger',
      duration: 2000
    })
    return
  }

  const labelPrinters = {
    a: 'labelprinter-1',
    b: 'labelprinter-2',
    c: 'labelprinter-3',
    d: 'labelprinter-4',
    e: 'labelprinter-5',
    f: 'labelprinter-6',
  }
  let labelPrinter = 'labelprinter-2'
  if(labelPrinters[form.value.labelPrinterId]) {
    labelPrinter = labelPrinters[form.value.labelPrinterId]
  }

  const doc = new jsPDF({
    orientation: 'l',
    unit: 'mm',
    format: 'a8',
    putOnlyUsedFonts: true,
    compress: true
  })
  try {
    doc.html(DOMPurify.sanitize('<div></div>'), {
      callback: (doc) => {
        try {
          doc.addPage()

          let no = 2;
          for(let entry of (locators.value ?? [])) {
            // Add the selected labelPrinterId to each entry
            entry.labelPrinterId = form.value.labelPrinterId ?? 'b'
            labelByPrinter(doc, no, entry)

            no++
          }

          doc.deletePage(1)
          doc.deletePage(Number(no) - 1)

          if(Number(locators.value?.length ?? 0) >= 1) {
            if(type === 'server') {
              serverSidePrinting({
                pathName: `locator-labels/${new Date().getFullYear()}`,
                fileName: `${date.now().replace(/\-|\:/g, '_').replace(' ', '-LABELS-')}.pdf`,
                fileContent: doc.output('dataurlstring')?.replace('data:application/pdf;filename=generated.pdf;base64,', ''),
                labelPrinterId: form.value.labelPrinterId ?? 'b',
              })
            } else if(type === 'server-download') {
              doc.save(`${date.now().replace(/\-|\:/g, '_').replace(' ', '-LABELS-')}.pdf`)
              serverSidePrinting({
                pathName: `locator-labels/${new Date().getFullYear()}`,
                fileName: `${date.now().replace(/\-|\:/g, '_').replace(' ', '-LABELS-')}.pdf`,
                fileContent: doc.output('dataurlstring')?.replace('data:application/pdf;filename=generated.pdf;base64,', ''),
                labelPrinterId: form.value.labelPrinterId ?? 'b',
              })
            } else {
              doc.save(`${date.now().replace(/\-|\:/g, '_').replace(' ', '-LABELS-')}.pdf`)
            }
          } else {
            toast({
              message: 'Please add at least one line first before pressing print labels button!',
              type: 'is-warning',
              duration: 2000
            })
          }
        } catch (error) {
          console.error('PDF generation error:', error)
          toast({
            message: 'Error generating PDF labels!',
            type: 'is-danger',
            duration: 2000
          })
        }
      },
      width: 263,
      windowWidth: 263,
      x: 0,
      y: 0,
      autoPaging: 'text',
    })
  } catch (error) {
    console.error('PDF initialization error:', error)
    toast({
      message: 'Failed to initialize PDF generation!',
      type: 'is-danger',
      duration: 2000
    })
  }
}

const breadCrumb = computed(() => ([
  { link: '#', text: 'Materials'},
  { link: '#', text: 'Locator Labels', active: true}
]))
</script>

<template>
  <Head>
    <Title>Locator Label Printer</Title>
  </Head>

  <NuxtLayout name="new-dash">
    <NewBreadCrumb :items="breadCrumb" />

    <div class="banner">
      <div class="px-1.5rem pt-1.5rem">
        <div class="d-flex justify-between p-1.5rem gap-1.5rem">
          <div class="legend w-100pct">
            <label class="label d-block">Warehouse</label>
            <ClientOnly>
              <SelectBox v-model="form.warehouseId" :options="getOptions?.['warehouses']?.records || [{id: form.warehouseId, Name: form.warehouse}]" prop="Name" dataprop="id" datatype="string" :size="5" @click="setOptions('models/m_warehouse', 'warehouses')" :loading="loading?.['warehouses'] ?? true" placeholder="----" />
            </ClientOnly>
          </div>
          <div class="legend w-100pct">
            <label class="label d-block">Locator Type</label>
            <ClientOnly>
              <SelectBox v-model="form.locatorTypeId" :options="getOptions?.['locator_types']?.records || [{id: form.locatorTypeId, Name: form.locatorType}]" prop="Name" dataprop="id" datatype="string" :size="5" @click="setOptions('models/m_locatortype', 'locator_types')" :loading="loading?.['locator_types'] ?? true" placeholder="----" />
            </ClientOnly>
          </div>
          <div class="legend w-100pct">
            <label class="label d-block">Label Printer</label>
            <ClientOnly>
              <SelectBox v-model="form.labelPrinterId" :options="getOptions?.['label_printers']?.reflist || [{value: form.labelPrinterId, name: form.labelPrinter}]" prop="name" dataprop="value" datatype="string" :size="5" @load="setOptions('references/labelprinter', 'label_printers')" @change="save" :loading="loading?.['label_printers'] ?? true" />
            </ClientOnly>
          </div>
        </div>
        <div class="d-flex justify-between p-1.5rem gap-1.5rem">
          <div class="legend w-100pct">
            <label class="label d-block">X</label>
            <input type="text" v-model="form.x" class="input" />
          </div>
          <div class="legend w-100pct">
            <label class="label d-block">Y</label>
            <input type="text" v-model="form.y" class="input" />
          </div>
          <div class="legend w-100pct">
            <label class="label d-block">Z</label>
            <input type="text" v-model="form.z" class="input" />
          </div>
        </div>
      </div>

      <div class="px-3rem d-flex justifyContent-flexEnd gap-10px">
        <button type="button" class="button" @click="filterLocatorChooser">Submit</button>
        <button type="button" @click="printLabels('server')" class="button">Print Labels (Server Only)</button>
        <button type="button" @click="printLabels('download')" class="button">Print Labels (Download Only)</button>
        <button type="button" @click="printLabels('server-download')" class="button">Print Labels (Server + Download)</button>
      </div>

      <div class="p-1.5rem">
        <div class="p-1.5rem">
          <table class="table tableList tableFlush">
            <thead>
            <tr>
              <th>#</th>
              <th>Locator</th>
              <th>Warehouse</th>
              <th>Locator Type</th>
              <th>X</th>
              <th>Y</th>
              <th>Z</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="(item, index) in locators" :key="index">
              <td>{{ Number(index) + 1 }}</td>
              <td>{{ item?.M_Locator_ID?.identifier ?? '' }}</td>
              <td>{{ item?.M_Warehouse_ID?.identifier ?? '' }}</td>
              <td>{{ item?.M_LocatorType_ID?.identifier ?? '' }}</td>
              <td>{{ item?.X ?? '' }}</td>
              <td>{{ item?.Y ?? '' }}</td>
              <td>{{ item?.Z ?? '' }}</td>
            </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </NuxtLayout>
</template>