<template>
  <n-modal
    :show="show"
    preset="card"
    title="工单打印预览"
    :mask-closable="false"
    :style="{ width: 'min(980px, 96vw)' }"
    @update:show="emit('update:show', $event)"
  >
    <n-spin :show="loading">
      <div class="wo-preview-stage">
        <div v-if="!order && !loading" class="wo-preview-empty">暂无工单数据</div>
        <div v-else ref="sheetsRef" class="wo-preview-pages">
          <section
            v-for="page in pages"
            :key="page.index"
            class="wo-a4-sheet"
          >
            <div class="wo-a4-frame">
              <header class="wo-a4-head" :class="{ 'is-cont': page.index > 1 }">
                <div>
                  <h1 class="wo-a4-title">
                    {{ page.index === 1 ? '工序计划工单' : '工序计划工单（续）' }}
                  </h1>
                  <div class="wo-a4-id">工单号　<b>{{ workOrderCode || '未赋码' }}</b></div>
                </div>
                <div class="wo-a4-qr">
                  <div class="wo-a4-qr-box">
                    <img v-if="qrDataUrl" :src="qrDataUrl" alt="工单号二维码" />
                    <div v-else class="wo-a4-qr-empty">无码</div>
                  </div>
                  <div class="wo-a4-qr-cap">扫码</div>
                </div>
              </header>

              <dl v-if="page.index === 1" class="wo-a4-meta">
                <div class="wo-a4-meta-item">
                  <dt>生产令号</dt>
                  <dd>{{ text(order?.mainCode) }}</dd>
                </div>
                <div class="wo-a4-meta-item">
                  <dt>生产订单</dt>
                  <dd>{{ text(order?.orderCode) }}</dd>
                </div>
                <div class="wo-a4-meta-item">
                  <dt>计划数量</dt>
                  <dd>{{ order?.quantity ?? '-' }}</dd>
                </div>
                <div class="wo-a4-meta-item">
                  <dt>生产车间</dt>
                  <dd>{{ text(order?.workshopName) }}</dd>
                </div>
                <div class="wo-a4-meta-item is-wide">
                  <dt>物料</dt>
                  <dd>{{ materialText }}</dd>
                </div>
                <div class="wo-a4-meta-item">
                  <dt>计划开工</dt>
                  <dd>{{ formatTime(order?.beginTime) }}</dd>
                </div>
                <div class="wo-a4-meta-item">
                  <dt>计划完工</dt>
                  <dd>{{ formatTime(order?.endTime) }}</dd>
                </div>
              </dl>

              <div class="wo-a4-table-wrap">
                <table class="wo-a4-table">
                  <colgroup>
                    <col class="col-no" />
                    <col class="col-name" />
                    <col class="col-time" />
                    <col class="col-time" />
                    <col class="col-qty" />
                  </colgroup>
                  <thead>
                    <tr>
                      <th>工序号</th>
                      <th>工序名称</th>
                      <th>计划开始</th>
                      <th>计划结束</th>
                      <th>数量</th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr
                      v-for="(row, idx) in page.rows"
                      :key="row.planId ?? `${page.index}-${idx}`"
                    >
                      <td>{{ row.operNumber ?? '-' }}</td>
                      <td class="is-left">{{ text(row.processName) }}</td>
                      <td>{{ formatTime(row.planStartTime || row.beginTime) }}</td>
                      <td>{{ formatTime(row.planFinishTime || row.endTime) }}</td>
                      <td>{{ row.quantity ?? '-' }}</td>
                    </tr>
                  </tbody>
                </table>
                <div v-if="!page.rows.length" class="wo-a4-empty">本工单暂无工序计划</div>
              </div>

              <footer v-if="page.index === pages.length" class="wo-a4-foot">
                <div class="wo-a4-sign">
                  <div class="wo-a4-sign-cell">
                    <b>操作工</b>
                    <div class="wo-a4-sign-line" />
                  </div>
                  <div class="wo-a4-sign-cell">
                    <b>质检</b>
                    <div class="wo-a4-sign-line" />
                  </div>
                  <div class="wo-a4-sign-cell">
                    <b>班组确认</b>
                    <div class="wo-a4-sign-line" />
                  </div>
                </div>
                <div class="wo-a4-note">
                  <span>打印人 {{ printerName }}　{{ printedAt }}</span>
                  <span>{{ page.index }} / {{ page.total }}</span>
                </div>
              </footer>
              <div v-else class="wo-a4-note">
                <span>续页　{{ workOrderCode || '-' }}</span>
                <span>{{ page.index }} / {{ page.total }}</span>
              </div>
            </div>
          </section>
        </div>
      </div>
    </n-spin>

    <template #footer>
      <n-space justify="end">
        <n-button @click="emit('update:show', false)">关闭</n-button>
        <n-button type="primary" :disabled="!order || loading" @click="handlePrint">
          打印
        </n-button>
      </n-space>
    </template>
  </n-modal>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { NButton, NModal, NSpace, NSpin, useMessage } from 'naive-ui'
import QRCode from 'qrcode'
import printCss from './workOrderPrint.css?inline'
import './workOrderPrint.css'
import {
  type OrderProcessPlanVO,
  type ProcessPlanItemVO,
} from '@/api/orderProcessPlan'
import { useUserStore } from '@/stores/user'

const FIRST_PAGE_ROWS = 16
const NEXT_PAGE_ROWS = 20

const props = defineProps<{
  show: boolean
  order: OrderProcessPlanVO | null
  loading?: boolean
}>()

const emit = defineEmits<{
  'update:show': [value: boolean]
}>()

const message = useMessage()
const userStore = useUserStore()
const sheetsRef = ref<HTMLElement | null>(null)
const qrDataUrl = ref('')
const printedAt = ref('')

const workOrderCode = computed(() => props.order?.workOrderCode?.trim() || '')
const printerName = computed(() => userStore.nickname || '-')

const materialText = computed(() => {
  const name = props.order?.materialName || '-'
  const code = props.order?.materialCode
  return code ? `${name}  ${code}` : name
})

const sortedProcesses = computed(() => {
  return [...(props.order?.processList ?? [])].sort((a, b) => {
    const oa = a.operNumber ?? 0
    const ob = b.operNumber ?? 0
    if (oa !== ob) return oa - ob
    return (a.planId ?? 0) - (b.planId ?? 0)
  })
})

const pages = computed(() => {
  const list = sortedProcesses.value
  if (!list.length) {
    return [{ index: 1, total: 1, rows: [] as ProcessPlanItemVO[] }]
  }
  const chunks: ProcessPlanItemVO[][] = [list.slice(0, FIRST_PAGE_ROWS)]
  for (let i = FIRST_PAGE_ROWS; i < list.length; i += NEXT_PAGE_ROWS) {
    chunks.push(list.slice(i, i + NEXT_PAGE_ROWS))
  }
  return chunks.map((rows, i) => ({
    index: i + 1,
    total: chunks.length,
    rows,
  }))
})

function text(v?: string | null) {
  return v && String(v).trim() ? String(v) : '-'
}

function formatTime(val?: string | null) {
  if (!val) return '-'
  return val.length > 16 ? val.slice(0, 16) : val
}

function nowText() {
  const d = new Date()
  const p = (n: number) => String(n).padStart(2, '0')
  return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`
}

watch(
  () => [props.show, workOrderCode.value] as const,
  async ([visible, code]) => {
    if (!visible) return
    printedAt.value = nowText()
    if (!code) {
      qrDataUrl.value = ''
      return
    }
    try {
      qrDataUrl.value = await QRCode.toDataURL(code, {
        errorCorrectionLevel: 'M',
        margin: 1,
        width: 320,
        color: { dark: '#000000', light: '#ffffff' },
      })
    } catch {
      qrDataUrl.value = ''
    }
  },
  { immediate: true },
)

function handlePrint() {
  const html = sheetsRef.value?.innerHTML
  if (!html) {
    message.warning('没有可打印的内容')
    return
  }
  const iframe = document.createElement('iframe')
  iframe.setAttribute('aria-hidden', 'true')
  iframe.style.cssText = 'position:fixed;right:0;bottom:0;width:0;height:0;border:0;'
  document.body.appendChild(iframe)
  const doc = iframe.contentDocument
  if (!doc) {
    iframe.remove()
    message.error('无法打开打印预览')
    return
  }
  const title = workOrderCode.value || '工序计划工单'
  doc.open()
  doc.write(`<!DOCTYPE html><html><head><meta charset="utf-8"><title>${title}</title><style>${printCss}html,body{margin:0;background:#fff}</style></head><body>${html}</body></html>`)
  doc.close()
  const run = () => {
    iframe.contentWindow?.focus()
    iframe.contentWindow?.print()
    window.setTimeout(() => iframe.remove(), 800)
  }
  const imgs = Array.from(doc.images)
  if (!imgs.length) {
    run()
    return
  }
  Promise.all(
    imgs.map(
      (img) =>
        new Promise<void>((resolve) => {
          if (img.complete) resolve()
          else {
            img.onload = () => resolve()
            img.onerror = () => resolve()
          }
        }),
    ),
  ).then(run)
}
</script>

<style scoped>
.wo-preview-stage {
  max-height: 72vh;
  overflow: auto;
  padding: 12px;
  background: #e8e8e8;
}

.wo-preview-empty {
  padding: 48px 0;
  text-align: center;
  color: #666;
}

.wo-preview-pages {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.wo-preview-pages :deep(.wo-a4-sheet) {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
}
</style>
