<template>
  <view class="page">
    <view class="header-hero" :style="{ paddingTop: statusBarHeight + 'px' }">
      <view class="top-bar">
        <view class="top-left" @click="goBack">
          <AppIcon name="chevronLeft" size="sm" color="white" />
        </view>
        <view class="top-center">
          <text class="page-title">Print Log</text>
          <LocationPicker />
        </view>
        <view class="top-right" @click="isMenuOpen = true">
          <AppIcon name="menu" size="sm" color="white" />
        </view>
      </view>
    </view>

    <view class="view-toggle">
      <view
        class="toggle-btn"
        :class="{ active: viewMode === 'card' }"
        @click="viewMode = 'card'"
      >
        <AppIcon name="squares" size="sm" :color="viewMode === 'card' ? 'white' : 'gray'" />
        <text class="toggle-text">Card</text>
      </view>
      <view
        class="toggle-btn"
        :class="{ active: viewMode === 'list' }"
        @click="viewMode = 'list'"
      >
        <AppIcon name="list" size="sm" :color="viewMode === 'list' ? 'white' : 'gray'" />
        <text class="toggle-text">List</text>
      </view>
    </view>

    <scroll-view
      class="content"
      scroll-y
      :style="contentHeight > 0 ? { height: contentHeight + 'px' } : undefined"
      @scrolltolower="onScrollToLower"
    >
      <view v-if="loading && !items.length" class="state-block">
        <text class="state-text">Loading…</text>
      </view>
      <view v-else-if="!loading && !items.length" class="state-block">
        <text class="state-text">No print records</text>
      </view>

      <!-- 卡片视图 -->
      <view v-else-if="viewMode === 'card'" class="log-list">
        <view
          v-for="row in items"
          :key="row.taskId + '-' + row.copyIndex"
          class="log-card"
        >
          <view class="card-header">
            <text class="product-name">{{ row.productName || '无' }}</text>
            <text class="label-id">{{ shortRef(row) }}</text>
          </view>
          <view class="card-tags">
            <text class="tag">{{ tagLabelSize(row) }}</text>
            <text class="tag">{{ tagTypeName(row) }}</text>
          </view>
          <view class="card-details">
            <view class="detail-row">
              <AppIcon name="clock" size="sm" color="gray" />
              <text class="detail-text">{{ row.printedAt }}</text>
            </view>
            <view class="detail-row">
              <AppIcon name="user" size="sm" color="gray" />
              <text class="detail-text">{{ row.operatorName || '无' }}</text>
            </view>
            <view class="detail-row">
              <AppIcon name="mapPin" size="sm" color="gray" />
              <text class="detail-text">{{ row.locationName || '无' }}</text>
            </view>
          </view>
          <view class="card-footer">
            <view class="reprint-btn" @click="handleReprint(row)">
              <AppIcon name="printer" size="sm" color="white" />
              <text class="reprint-text">Reprint</text>
            </view>
          </view>
        </view>
        <view v-if="loadingMore" class="load-more">
          <text class="load-more-text">Loading more…</text>
        </view>
        <view v-else-if="!hasMore && items.length" class="load-more end">
          <text class="load-more-text">End of list</text>
        </view>
      </view>

      <!-- 列表视图 -->
      <view v-else class="log-table-wrap">
        <view class="log-table">
          <view class="log-table-header">
            <text class="th th-product">Product</text>
            <text class="th th-id">Ref</text>
            <text class="th th-size">Label size</text>
            <text class="th th-type">Type</text>
            <text class="th th-printed">Printed At</text>
            <text class="th th-action">Action</text>
          </view>
          <view
            v-for="row in items"
            :key="row.taskId + '-' + row.copyIndex"
            class="log-table-row"
          >
            <text class="td td-product">{{ row.productName || '无' }}</text>
            <text class="td td-id">{{ shortRef(row) }}</text>
            <text class="td td-size">{{ tagLabelSize(row) }}</text>
            <text class="td td-type">{{ tagTypeName(row) }}</text>
            <text class="td td-printed">{{ row.printedAt }}</text>
            <view class="td td-action">
              <view class="reprint-btn-sm" @click="handleReprint(row)">
                <AppIcon name="printer" size="sm" color="white" />
              </view>
            </view>
          </view>
        </view>
        <view v-if="loadingMore" class="load-more">
          <text class="load-more-text">Loading more…</text>
        </view>
      </view>
    </scroll-view>

    <SideMenu v-model="isMenuOpen" />

    <!-- 重打整页光栅与预览页一致：须绑定 width/height 像素，否则 canvasToTempFilePath 易空白 -->
    <canvas
      canvas-id="reprintLabelCanvas"
      id="reprintLabelCanvas"
      class="hidden-canvas"
      :style="{ width: reprintCanvasW + 'px', height: reprintCanvasH + 'px' }"
      :width="reprintCanvasW"
      :height="reprintCanvasH"
    />
  </view>
</template>

<script setup lang="ts">
import { ref, getCurrentInstance, nextTick } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import AppIcon from '../../components/AppIcon.vue'
import SideMenu from '../../components/SideMenu.vue'
import LocationPicker from '../../components/LocationPicker.vue'
import { getStatusBarHeight } from '../../utils/statusBar'
import { getCurrentStoreId } from '../../utils/stores'
import {
  fetchUsAppPrintLogList,
  postUsAppLabelReprint,
} from '../../services/usAppLabeling'
import { printFromPrintLogRow } from '../../utils/printFromPrintDataList'
import type { SystemTemplatePrintCanvasRasterOptions } from '../../utils/print/manager/printerManager'
import {
  getBluetoothConnection,
  getPrinterType,
  isNativeBaseClassicBluetoothTransport,
} from '../../utils/print/printerConnection'
import { getCurrentPrinterSummary } from '../../utils/print/manager/printerManager'
import { showNativeFastPrinterDebugModal } from '../../utils/print/showNativeFastPrinterDebugModal'
import { isUsAppSessionExpiredError } from '../../utils/usAppApiRequest'
import type { PrintLogItemDto } from '../../types/usAppLabeling'

const statusBarHeight = getStatusBarHeight()
const isMenuOpen = ref(false)
const viewMode = ref<'card' | 'list'>('card')

const reprintCanvasW = ref(400)
const reprintCanvasH = ref(400)
const contentHeight = ref(0)

/** 须在 setup 顶层取实例，异步回调里 getCurrentInstance() 为 null */
const reprintCanvasComponentProxy = getCurrentInstance()?.proxy

const applyReprintCanvasLayout: NonNullable<SystemTemplatePrintCanvasRasterOptions['applyLayout']> = async (
  layout,
) => {
  reprintCanvasW.value = layout.outW
  reprintCanvasH.value = layout.outH
  await nextTick()
}

const computeContentHeight = async () => {
  const inst = getCurrentInstance()?.proxy
  if (!inst) return
  await nextTick()
  const windowHeight = Number(uni.getSystemInfoSync().windowHeight || 0)
  const q = uni.createSelectorQuery().in(inst as any)
  q.select('.header-hero').boundingClientRect()
  q.select('.view-toggle').boundingClientRect()
  q.exec((rects: any[]) => {
    const headerH = Number(rects?.[0]?.height || 0)
    const toggleH = Number(rects?.[1]?.height || 0)
    const safe = Math.max(260, Math.round(windowHeight - headerH - toggleH))
    contentHeight.value = safe
  })
}

const items = ref<PrintLogItemDto[]>([])
const loading = ref(false)
const loadingMore = ref(false)
const pageIndex = ref(1)
const hasMore = ref(true)
const pageSize = 20

function shouldShowNativeFastDebugModal (): boolean {
  const summary = getCurrentPrinterSummary()
  return summary.type === 'builtin'
    || (summary.type === 'bluetooth' && isNativeBaseClassicBluetoothTransport())
}

function createClientRequestId (): string {
  const c = typeof globalThis !== 'undefined' ? (globalThis as { crypto?: Crypto }).crypto : undefined
  if (c && typeof c.randomUUID === 'function') {
    return c.randomUUID()
  }
  return `reprint-${Date.now()}-${Math.random().toString(36).slice(2, 12)}`
}

function shortRef (row: PrintLogItemDto): string {
  const b = String(row.batchId || row.taskId || '').trim()
  if (b.length > 14) return `${b.slice(0, 8)}…`
  return b || row.labelCode || '—'
}

/** 红框左：labelSizeText（兼容 PascalCase） */
function tagLabelSize (row: PrintLogItemDto): string {
  const raw = row.labelSizeText ?? (row as unknown as { LabelSizeText?: string }).LabelSizeText
  const s = String(raw ?? '').trim()
  return s || '无'
}

/** 红框右：typeName（兼容 PascalCase） */
function tagTypeName (row: PrintLogItemDto): string {
  const raw = row.typeName ?? (row as unknown as { TypeName?: string }).TypeName
  const s = String(raw ?? '').trim()
  return s || '无'
}

async function loadPage (reset: boolean) {
  const locationId = getCurrentStoreId()
  if (!locationId) {
    items.value = []
    return
  }
  if (reset) {
    pageIndex.value = 1
    hasMore.value = true
    loading.value = true
  } else {
    if (!hasMore.value || loadingMore.value) return
    loadingMore.value = true
  }
  try {
    const p = reset ? 1 : pageIndex.value
    const res = await fetchUsAppPrintLogList({
      locationId,
      skipCount: p,
      maxResultCount: pageSize,
    })
    if (reset) {
      items.value = res.items
    } else {
      items.value = [...items.value, ...res.items]
    }
    hasMore.value = items.value.length < res.totalCount
    if (res.items.length > 0) {
      pageIndex.value = p + 1
    }
  } catch (e) {
    if (!isUsAppSessionExpiredError(e)) {
      const msg = e instanceof Error ? e.message : 'Load failed'
      uni.showToast({ title: msg, icon: 'none', duration: 2500 })
    }
    if (reset) items.value = []
  } finally {
    loading.value = false
    loadingMore.value = false
  }
}

function onScrollToLower () {
  if (!loading.value && hasMore.value) {
    loadPage(false)
  }
}

onShow(() => {
  computeContentHeight()
  loadPage(true)
})

const handleReprint = async (row: PrintLogItemDto) => {
  const locationId = getCurrentStoreId()
  if (!locationId) {
    uni.showToast({ title: 'Please select a store', icon: 'none' })
    return
  }
  if (!getPrinterType()) {
    uni.showToast({ title: 'Please connect a printer first', icon: 'none' })
    return
  }
  uni.showLoading({ title: 'Rendering…', mask: true })
  let needShowNativeDebug = false
  try {
    /** 与预览一致：一体机/基座可走 native printTemplate，否则整页光栅；图片会先 hydration 再送基座 */
    await printFromPrintLogRow(row, {
      printQty: 1,
      onProgress: (pct) => {
        if (pct > 5 && pct < 100) {
          uni.showLoading({ title: `Printing ${pct}%`, mask: true })
        }
      },
      canvasRaster: reprintCanvasComponentProxy
        ? {
            canvasId: 'reprintLabelCanvas',
            componentInstance: reprintCanvasComponentProxy,
            applyLayout: applyReprintCanvasLayout,
          }
        : undefined,
    })
    const bt = getBluetoothConnection()
    uni.showLoading({ title: 'Saving…', mask: true })
    /** 出纸成功后再调接口 11 记重打（与文档「重复打印」落库一致） */
    await postUsAppLabelReprint({
      locationId,
      taskId: row.taskId,
      printQuantity: 1,
      clientRequestId: createClientRequestId(),
      printerMac: bt?.deviceId || undefined,
    })
    uni.showToast({ title: 'Done', icon: 'success' })
    needShowNativeDebug = shouldShowNativeFastDebugModal()
  } catch (e: unknown) {
    if (!isUsAppSessionExpiredError(e)) {
      const msg = e instanceof Error ? e.message : 'Reprint failed'
      uni.showToast({ title: msg, icon: 'none', duration: 3000 })
      needShowNativeDebug = shouldShowNativeFastDebugModal()
    }
  } finally {
    uni.hideLoading()
    if (needShowNativeDebug) {
      setTimeout(() => {
        void showNativeFastPrinterDebugModal()
      }, 500)
    }
  }
}

const goBack = () => {
  const pages = getCurrentPages()
  if (pages.length > 1) {
    uni.navigateBack()
  } else {
    uni.redirectTo({ url: '/pages/index/index' })
  }
}
</script>

<style scoped>
.page {
  min-height: 100vh;
  background: #f3f4f6;
  display: flex;
  flex-direction: column;
}

.header-hero {
  background: linear-gradient(135deg, #1F3A8A, #142a6c);
  padding: 16rpx 32rpx 24rpx;
}

.top-bar {
  height: 96rpx;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.top-left,
.top-right {
  width: 64rpx;
  height: 64rpx;
  border-radius: 999rpx;
  background: rgba(255, 255, 255, 0.15);
  display: flex;
  align-items: center;
  justify-content: center;
}

.top-center {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.page-title {
  font-size: 34rpx;
  font-weight: 600;
  color: #fff;
}

.state-block {
  padding: 80rpx 32rpx;
  text-align: center;
}

.state-text {
  font-size: 28rpx;
  color: #6b7280;
}

.content {
  padding: 24rpx 28rpx 40rpx;
  box-sizing: border-box;
  min-height: 260px;
}

.log-list {
  display: flex;
  flex-direction: column;
  gap: 20rpx;
}

.log-card {
  background: #fff;
  border-radius: 24rpx;
  padding: 0;
  box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.04);
  overflow: hidden;
  border: 1rpx solid #e5e7eb;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 28rpx 28rpx 20rpx;
  background: linear-gradient(180deg, #fafbfc 0%, #fff 100%);
}

.product-name {
  font-size: 34rpx;
  font-weight: 700;
  color: #111827;
  flex: 1;
  line-height: 1.3;
  letter-spacing: -0.02em;
}

.label-id {
  font-size: 22rpx;
  color: #9ca3af;
  flex-shrink: 0;
  margin-left: 16rpx;
  padding: 6rpx 12rpx;
  background: #f3f4f6;
  border-radius: 8rpx;
}

.card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 12rpx;
  padding: 0 28rpx 20rpx;
}

.tag {
  font-size: 24rpx;
  color: #1F3A8A;
  background: #e8ecf5;
  padding: 8rpx 18rpx;
  border-radius: 10rpx;
  font-weight: 500;
}

.card-details {
  display: flex;
  flex-direction: column;
  gap: 16rpx;
  padding: 24rpx 28rpx;
  background: #fafbfc;
  border-top: 1rpx solid #e5e7eb;
}

.detail-row {
  display: flex;
  align-items: center;
  gap: 12rpx;
}

.detail-text {
  font-size: 28rpx;
  color: #4b5563;
  line-height: 1.4;
}

.card-footer {
  padding: 20rpx 28rpx 24rpx;
  background: #fff;
  border-top: 1rpx solid #e5e7eb;
}

.reprint-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10rpx;
  padding: 16rpx 32rpx;
  background: linear-gradient(135deg, #1F3A8A, #1447E6);
  border-radius: 14rpx;
  box-shadow: 0 4rpx 12rpx rgba(31, 58, 138, 0.25);
}

.reprint-btn:active {
  opacity: 0.9;
  transform: scale(0.98);
}

.reprint-text {
  font-size: 28rpx;
  font-weight: 600;
  color: #fff;
}

.view-toggle {
  display: flex;
  gap: 12rpx;
  padding: 16rpx 28rpx;
  background: #fff;
  border-bottom: 1rpx solid #e5e7eb;
}

.toggle-btn {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8rpx;
  padding: 16rpx 24rpx;
  border-radius: 12rpx;
  background: #f3f4f6;
  transition: all 0.2s;
}

.toggle-btn.active {
  background: linear-gradient(135deg, #1F3A8A, #1447E6);
}

.toggle-btn.active .toggle-text {
  color: #fff;
}

.toggle-text {
  font-size: 26rpx;
  font-weight: 500;
  color: #6b7280;
}

.log-table-wrap {
  background: #fff;
  border-radius: 20rpx;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.04);
  border: 1rpx solid #e5e7eb;
}

.log-table-wrap::-webkit-scrollbar {
  height: 6px;
}
.log-table-wrap::-webkit-scrollbar-thumb {
  background: #d1d5db;
  border-radius: 3px;
}
.log-table-wrap::-webkit-scrollbar-track {
  background: #f3f4f6;
}

.log-table {
  width: max-content;
  min-width: 100%;
}

.log-table-header {
  display: flex;
  padding: 24rpx 28rpx;
  gap: 16rpx;
  background: #fafbfc;
  border-bottom: 1rpx solid #e5e7eb;
  font-size: 24rpx;
  font-weight: 600;
  color: #6b7280;
}

.log-table-row {
  display: flex;
  padding: 24rpx 28rpx;
  gap: 16rpx;
  border-bottom: 1rpx solid #e5e7eb;
  align-items: center;
  font-size: 26rpx;
}

.log-table-row:last-child {
  border-bottom: none;
}

.th, .td {
  flex-shrink: 0;
  white-space: nowrap;
}

.th-product, .td-product { flex: 0 0 auto; min-width: 140rpx; }
.th-id, .td-id { flex: 0 0 auto; min-width: 160rpx; }
.th-size, .td-size { flex: 0 0 auto; min-width: 220rpx; max-width: 360rpx; }
.th-type, .td-type { flex: 0 0 auto; min-width: 120rpx; }
.th-printed, .td-printed { flex: 0 0 auto; min-width: 200rpx; }
.th-action, .td-action {
  flex: 0 0 80rpx;
  width: 80rpx;
  min-width: 80rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.td-product { color: #111827; font-weight: 500; }
.td-id { color: #6b7280; font-size: 24rpx; }
.td-size,
.td-type { color: #4b5563; font-size: 24rpx; }
.td-printed { color: #4b5563; }

.reprint-btn-sm {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 64rpx;
  height: 64rpx;
  background: linear-gradient(135deg, #1F3A8A, #1447E6);
  border-radius: 12rpx;
}

.reprint-btn-sm:active {
  opacity: 0.9;
}

.load-more {
  padding: 24rpx;
  text-align: center;
}
.load-more.end .load-more-text {
  color: #9ca3af;
}
.load-more-text {
  font-size: 24rpx;
  color: #6b7280;
}

.hidden-canvas {
  position: fixed;
  left: -9999px;
  top: 0;
  opacity: 0;
  pointer-events: none;
}
</style>
