/**
 * Machine print selection and execution logic.
 *
 * Extracted from pages/machine/[id].vue.
 */

import { ref, reactive, nextTick } from 'vue'
import { buildMachinePrintContext, buildMachinePrintHtml } from '~/utils/printTemplates/machineReport'

type AnyRecord = Record<string, unknown>

export interface PrintSelection {
  machine: { info: boolean; customFields: boolean; documents: boolean }
  components: Record<string, boolean>
  pieces: Record<string, boolean>
}

export function useMachinePrint() {
  const printModalOpen = ref(false)
  const printSelection = reactive<PrintSelection>({
    machine: { info: true, customFields: true, documents: true },
    components: {},
    pieces: {},
  })

  const ensurePrintSelectionEntries = (
    components: AnyRecord[],
    machinePieces: AnyRecord[],
  ) => {
    printSelection.machine.info ??= true
    printSelection.machine.customFields ??= true
    printSelection.machine.documents ??= true

    const ensureComponent = (component: AnyRecord) => {
      if (component?.id !== undefined && printSelection.components[component.id as string] === undefined) {
        printSelection.components[component.id as string] = true
      }
      ;((component.pieces || []) as AnyRecord[]).forEach((piece) => {
        if (piece?.id !== undefined && printSelection.pieces[piece.id as string] === undefined) {
          printSelection.pieces[piece.id as string] = true
        }
      })
      ;((component.subComponents || []) as AnyRecord[]).forEach(ensureComponent)
    }

    components.forEach(ensureComponent)
    machinePieces.forEach((piece) => {
      if (piece?.id !== undefined && printSelection.pieces[piece.id as string] === undefined) {
        printSelection.pieces[piece.id as string] = true
      }
    })
  }

  const setAllPrintSelection = (
    value: boolean,
    components: AnyRecord[],
    machinePieces: AnyRecord[],
  ) => {
    ensurePrintSelectionEntries(components, machinePieces)
    printSelection.machine.info = value
    printSelection.machine.customFields = value
    printSelection.machine.documents = value
    Object.keys(printSelection.components).forEach((key) => {
      printSelection.components[key] = value
    })
    Object.keys(printSelection.pieces).forEach((key) => {
      printSelection.pieces[key] = value
    })
  }

  const openPrintModal = (components: AnyRecord[], machinePieces: AnyRecord[]) => {
    ensurePrintSelectionEntries(components, machinePieces)
    printModalOpen.value = true
  }

  const closePrintModal = () => {
    printModalOpen.value = false
  }

  const printMachine = (
    machine: AnyRecord,
    machineName: string,
    machineReference: string,
    machinePieces: AnyRecord[],
    components: AnyRecord[],
    currentSelection: PrintSelection = printSelection,
  ) => {
    if (typeof window === 'undefined') return

    // machineReport.js has no type annotations; cast to avoid inferred never[] params
    const context = (buildMachinePrintContext as unknown as (config: Record<string, unknown>) => Record<string, unknown>)({
      machine,
      machineName,
      machineReference,
      machinePieces,
      components,
      selection: currentSelection,
    })
    const styles = Array.from(document.querySelectorAll('link[rel="stylesheet"], style'))
      .map((node) => node.outerHTML)
      .join('')

    const htmlContent = buildMachinePrintHtml(context, styles)

    const iframe = document.createElement('iframe')
    iframe.style.position = 'fixed'
    iframe.style.right = '0'
    iframe.style.bottom = '0'
    iframe.style.width = '0'
    iframe.style.height = '0'
    iframe.style.border = '0'
    iframe.setAttribute('title', 'print-frame')
    document.body.appendChild(iframe)

    const iframeWindow = iframe.contentWindow
    const iframeDocument = iframe.contentDocument || iframeWindow?.document
    if (!iframeDocument || !iframeWindow) {
      iframe.remove()
      return
    }

    iframeDocument.open()
    iframeDocument.write(htmlContent)
    iframeDocument.close()

    const triggerPrint = () => {
      iframeWindow.focus()
      iframeWindow.print()
      setTimeout(() => {
        iframe.remove()
      }, 1000)
    }

    if (iframeDocument.readyState === 'complete') {
      setTimeout(triggerPrint, 50)
    } else {
      iframe.onload = () => setTimeout(triggerPrint, 50)
    }
  }

  const handlePrintConfirm = async (
    machine: AnyRecord,
    machineName: string,
    machineReference: string,
    machinePieces: AnyRecord[],
    components: AnyRecord[],
  ) => {
    closePrintModal()
    await nextTick()
    printMachine(machine, machineName, machineReference, machinePieces, components, printSelection)
  }

  return {
    printModalOpen,
    printSelection,
    ensurePrintSelectionEntries,
    setAllPrintSelection,
    openPrintModal,
    closePrintModal,
    printMachine,
    handlePrintConfirm,
  }
}
