<script lang="ts" setup>
import type { TraceabilityApi } from '#/api';

import { computed, onMounted, ref } from 'vue';

import { Page } from '@vben/common-ui';

import { useQRCode } from '@vueuse/integrations/useQRCode';
import {
  Button,
  Card,
  Col,
  Empty,
  Input,
  message,
  Row,
  Tag,
} from 'ant-design-vue';

import { getTraceabilityBatches, getTraceabilityPreviewDetail } from '#/api';

import {
  buildCoordinateEmbedUrl,
  buildCoordinateMapUrl,
  formatFieldValue,
  getFieldDisplayStyle,
  getImagePreviewSrc,
} from './shared';

const loading = ref(false);
const batches = ref<TraceabilityApi.BatchSummary[]>([]);
const queryCode = ref('');
const detail = ref<null | TraceabilityApi.PublicDetail>(null);

const publicLink = computed(() => detail.value?.batch.publicUrl ?? '');
const qrCode = useQRCode(publicLink, {
  errorCorrectionLevel: 'M',
  margin: 2,
  width: 220,
});
const qrDownloadName = computed(
  () => `${detail.value?.batch.batchCode || 'batch'}.png`,
);

function downloadQrCode(dataUrl: string, fileName: string) {
  if (!dataUrl) return;
  const link = document.createElement('a');
  link.href = dataUrl;
  link.download = fileName;
  document.body.append(link);
  link.click();
  link.remove();
}

function downloadConsumerQrCode() {
  downloadQrCode(qrCode.value, qrDownloadName.value);
}

async function loadBatches() {
  batches.value = await getTraceabilityBatches();
  if (!queryCode.value && batches.value[0]) {
    queryCode.value = batches.value[0].batchCode;
    await search();
  }
}

async function search() {
  if (!queryCode.value.trim()) {
    message.warning('请输入批次编码');
    return;
  }
  loading.value = true;
  try {
    detail.value = await getTraceabilityPreviewDetail(queryCode.value.trim());
  } finally {
    loading.value = false;
  }
}

function getStatusLabel(status: string) {
  if (status === 'completed') return '已完成';
  if (status === 'pending') return '进行中';
  if (status === 'published') return '已发布';
  if (status === 'draft') return '未发布';
  return status || '进行中';
}

function getFieldLabel(fields: TraceabilityApi.FieldDefinition[], key: string) {
  return fields.find((field) => field.key === key)?.label || key;
}

function getDisplayEntries(step: TraceabilityApi.BatchStep) {
  return Object.entries(step.values).map(([key, value]) => ({
    key,
    label: getFieldLabel(step.fields, key),
    type: step.fields.find((field) => field.key === key)?.type || 'string',
    field: step.fields.find((field) => field.key === key),
    value,
  }));
}

onMounted(loadBatches);
</script>

<template>
  <Page auto-content-height>
    <div class="trace-consumer">
      <Card class="panel-card search-panel">
        <div class="search-panel__meta">
          <div>
            <span class="panel-kicker">消费者页预览</span>
            <h2>溯源信息预览</h2>
          </div>
          <div class="search-box">
            <Input
              v-model:value="queryCode"
              placeholder="请输入批次编码，如：TR-2026-000001"
              @press-enter="search"
            />
            <Button type="primary" :loading="loading" @click="search">
              查询
            </Button>
          </div>
        </div>
      </Card>

      <template v-if="detail">
        <Row :gutter="[16, 16]" class="metrics-row">
          <Col :lg="6" :sm="12" :xs="24">
            <Card class="panel-card stat-panel">
              <span>批次名称</span>
              <strong>{{ detail.batch.batchName }}</strong>
              <small>{{ detail.batch.batchCode }}</small>
            </Card>
          </Col>
          <Col :lg="6" :sm="12" :xs="24">
            <Card class="panel-card stat-panel">
              <span>当前状态</span>
              <strong>{{ detail.batch.status }}</strong>
              <small>{{ detail.batch.productName || '未设置产品名称' }}</small>
            </Card>
          </Col>
          <Col :lg="6" :sm="12" :xs="24">
            <Card class="panel-card stat-panel">
              <span>扫码次数</span>
              <strong>{{ detail.batch.scanCount }}</strong>
              <small>{{ detail.batch.templateName }}</small>
            </Card>
          </Col>
          <Col :lg="6" :sm="12" :xs="24">
            <Card class="panel-card stat-panel">
              <span>公开节点数</span>
              <strong>{{ detail.publicSections.length }}</strong>
              <small>业务节点 {{ detail.businessSections.length }} 个</small>
            </Card>
          </Col>
        </Row>

        <Row :gutter="[16, 16]" class="feature-row">
          <Col :lg="8" :xs="24">
            <Card class="panel-card qr-panel" title="二维码">
              <template #extra>
                <Button
                  v-if="publicLink"
                  size="small"
                  type="primary"
                  @click="downloadConsumerQrCode"
                >
                  保存二维码
                </Button>
              </template>
              <div class="qr-wrap">
                <img :src="qrCode" alt="溯源二维码" class="qr-image" />
                <div class="qr-meta">
                  <strong>扫码查看溯源页</strong>
                  <p>{{ publicLink }}</p>
                </div>
              </div>
            </Card>
          </Col>
          <Col :lg="16" :xs="24">
            <Card class="panel-card access-panel" title="访问信息">
              <div class="access-layout">
                <div class="access-main">
                  <div class="access-main__head">
                    <span>消费者访问地址</span>
                    <strong>{{ publicLink }}</strong>
                  </div>
                  <p>
                    {{
                      detail.batch.summary ||
                      '该批次已完成发布，可直接用于消费者扫码访问。'
                    }}
                  </p>
                </div>
                <div class="access-meta">
                  <div class="access-card">
                    <span>发布时间</span>
                    <strong>{{ detail.batch.publishedAt || '未发布' }}</strong>
                  </div>
                  <div class="access-card">
                    <span>产品名称</span>
                    <strong>{{
                      detail.batch.productName || '未设置产品名称'
                    }}</strong>
                  </div>
                  <div class="access-card">
                    <span>所属模板</span>
                    <strong>{{ detail.batch.templateName }}</strong>
                  </div>
                  <div class="access-card">
                    <span>标签</span>
                    <strong>{{
                      detail.batch.tags.join('、') || '暂无标签'
                    }}</strong>
                  </div>
                </div>
              </div>
            </Card>
          </Col>
        </Row>

        <Row :gutter="[16, 16]">
          <Col :lg="9" :xs="24">
            <Card class="panel-card" title="公开资料区">
              <div class="section-stack">
                <div
                  v-for="item in detail.publicSections"
                  :key="item.id"
                  class="section-card"
                >
                  <div class="section-card__head">
                    <strong>{{ item.name }}</strong>
                    <Tag color="blue">公开</Tag>
                  </div>
                  <p>{{ item.description || '企业与资质信息展示区' }}</p>
                  <div class="kv-grid">
                    <div
                      v-for="entry in getDisplayEntries(item)"
                      :key="entry.key"
                      class="kv-card"
                    >
                      <span>{{ entry.label }}</span>
                      <img
                        v-if="entry.type === 'image' && entry.value"
                        :src="
                          getImagePreviewSrc(
                            entry.value,
                            item.valuePreviewUrls?.[entry.key],
                          )
                        "
                        :alt="entry.label"
                        class="consumer-image"
                      />
                      <div
                        v-else-if="entry.type === 'coordinate' && entry.value"
                        class="coordinate-preview-card"
                      >
                        <iframe
                          v-if="buildCoordinateEmbedUrl(entry.value)"
                          :src="buildCoordinateEmbedUrl(entry.value)"
                          class="coordinate-preview-map"
                          loading="lazy"
                          referrerpolicy="no-referrer-when-downgrade"
                          :title="entry.label"
                        ></iframe>
                        <strong :style="getFieldDisplayStyle(entry.field)">
                          {{ formatFieldValue(entry.value) }}
                        </strong>
                        <a
                          v-if="buildCoordinateMapUrl(entry.value)"
                          :href="buildCoordinateMapUrl(entry.value)"
                          target="_blank"
                          rel="noreferrer"
                          >打开地图</a
                        >
                      </div>
                      <strong
                        v-else
                        :style="getFieldDisplayStyle(entry.field)"
                      >
                        {{ formatFieldValue(entry.value) }}
                      </strong>
                    </div>
                  </div>
                </div>
              </div>
            </Card>
          </Col>

          <Col :lg="15" :xs="24">
            <Card class="panel-card" title="溯源时间轴">
              <div class="timeline">
                <div
                  v-for="(item, index) in detail.businessSections"
                  :key="item.id"
                  class="timeline-item"
                >
                  <div class="timeline-rail">
                    <span class="dot"></span>
                    <span
                      v-if="index !== detail.businessSections.length - 1"
                      class="line"
                    ></span>
                  </div>
                  <div class="timeline-card">
                    <div class="timeline-card__head">
                      <div>
                        <h3>{{ item.name }}</h3>
                        <p>{{ item.description || '流程记录' }}</p>
                      </div>
                      <Tag>{{ getStatusLabel(item.status) }}</Tag>
                    </div>
                    <div class="kv-grid">
                      <div
                        v-for="entry in getDisplayEntries(item)"
                        :key="entry.key"
                        class="kv-card"
                      >
                        <span>{{ entry.label }}</span>
                        <img
                          v-if="entry.type === 'image' && entry.value"
                          :src="
                            getImagePreviewSrc(
                              entry.value,
                              item.valuePreviewUrls?.[entry.key],
                            )
                          "
                          :alt="entry.label"
                          class="consumer-image"
                        />
                        <div
                          v-else-if="entry.type === 'coordinate' && entry.value"
                          class="coordinate-preview-card"
                        >
                          <iframe
                            v-if="buildCoordinateEmbedUrl(entry.value)"
                            :src="buildCoordinateEmbedUrl(entry.value)"
                            class="coordinate-preview-map"
                            loading="lazy"
                            referrerpolicy="no-referrer-when-downgrade"
                            :title="entry.label"
                          ></iframe>
                          <strong :style="getFieldDisplayStyle(entry.field)">
                            {{ formatFieldValue(entry.value) }}
                          </strong>
                          <a
                            v-if="buildCoordinateMapUrl(entry.value)"
                            :href="buildCoordinateMapUrl(entry.value)"
                            target="_blank"
                            rel="noreferrer"
                            >打开地图</a
                          >
                        </div>
                        <strong v-else :style="getFieldDisplayStyle(entry.field)">
                          {{ formatFieldValue(entry.value) }}
                        </strong>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </Card>
          </Col>
        </Row>
      </template>

      <Card v-else class="panel-card empty-wrap">
        <Empty description="输入批次编码后查看消费者端预览" />
      </Card>
    </div>
  </Page>
</template>

<style scoped>
.trace-consumer {
  display: grid;
  gap: 16px;
  padding: 4px;
}

.panel-card {
  border-radius: 22px;
}

.search-panel {
  background: linear-gradient(135deg, #ffffff, #f8fbff);
}

.search-panel__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.panel-kicker {
  display: inline-flex;
  padding: 6px 12px;
  border-radius: 999px;
  background: #edf3ff;
  color: #1d4ed8;
  font-size: 12px;
  font-weight: 600;
}

.search-panel h2 {
  margin: 12px 0 0;
  font-size: 28px;
}

.search-box {
  display: grid;
  grid-template-columns: minmax(0, 360px) auto;
  gap: 12px;
  width: min(100%, 520px);
}

.stat-panel span,
.kv-card span,
.access-card span {
  color: #7d8899;
  font-size: 12px;
}

.stat-panel strong,
.access-card strong {
  display: block;
  margin-top: 8px;
  font-size: 18px;
  word-break: break-word;
}

.stat-panel small {
  display: block;
  margin-top: 8px;
  color: #98a2b3;
}

.metrics-row :deep(.ant-col),
.feature-row :deep(.ant-col) {
  display: flex;
}

.metrics-row .panel-card,
.feature-row .panel-card {
  width: 100%;
  height: 100%;
}

.stat-panel :deep(.ant-card-body),
.access-panel :deep(.ant-card-body),
.qr-panel :deep(.ant-card-body) {
  height: 100%;
}

.stat-panel {
  min-height: 138px;
}

.qr-wrap {
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 16px;
  min-height: 100%;
}

.qr-image {
  width: 220px;
  height: 220px;
  border-radius: 18px;
  border: 1px solid #edf1f7;
  background: #fff;
  padding: 12px;
}

.qr-meta {
  text-align: center;
}

.qr-meta strong {
  display: block;
  font-size: 18px;
}

.qr-meta p {
  margin: 10px 0 0;
  color: #667085;
  word-break: break-all;
}

.access-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 14px;
}

.access-main {
  border: 1px solid #dfe9fb;
  border-radius: 20px;
  background: linear-gradient(135deg, #f7faff, #eef4ff);
  padding: 18px;
  min-width: 0;
}

.access-main__head {
  display: grid;
  gap: 8px;
}

.access-main span {
  color: #7d8899;
  font-size: 12px;
}

.access-main strong {
  display: block;
  color: #1d4ed8;
  font-size: 18px;
  line-height: 1.6;
  word-break: break-all;
}

.access-main p {
  margin: 14px 0 0;
  color: #5f6b7c;
  line-height: 1.7;
  word-break: break-word;
}

.access-meta {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  min-width: 0;
}

.access-card {
  border: 1px solid #edf1f7;
  border-radius: 18px;
  background: #fafcff;
  padding: 16px;
  min-height: 108px;
  min-width: 0;
}

.access-card strong {
  line-height: 1.6;
  word-break: break-word;
  white-space: pre-wrap;
}

.section-stack {
  display: grid;
  gap: 12px;
}

.section-card,
.timeline-card {
  border: 1px solid #edf1f7;
  border-radius: 18px;
  background: #fff;
  padding: 16px;
}

.section-card__head,
.timeline-card__head {
  display: flex;
  justify-content: space-between;
  align-items: start;
  gap: 12px;
}

.section-card p,
.timeline-card p {
  margin: 8px 0 0;
  color: #6b7280;
}

.timeline-card strong {
  white-space: pre-wrap;
  word-break: break-word;
}

.kv-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin-top: 14px;
}

.kv-card {
  border: 1px solid #eef2f7;
  border-radius: 14px;
  background: #fafcff;
  padding: 12px;
}

.kv-card strong {
  display: block;
  margin-top: 8px;
  white-space: pre-wrap;
  word-break: break-word;
}

.consumer-image {
  display: block;
  width: 100%;
  max-height: 220px;
  margin-top: 10px;
  border: 1px solid #e2e8f0;
  border-radius: 14px;
  object-fit: cover;
  background: #fff;
}

.coordinate-preview-card {
  display: grid;
  gap: 10px;
}

.coordinate-preview-map {
  width: 100%;
  min-height: 180px;
  border: 1px solid #e2e8f0;
  border-radius: 14px;
  background: #fff;
}

.coordinate-preview-card a {
  color: #1d4ed8;
  font-size: 12px;
}

.timeline {
  display: grid;
  gap: 16px;
}

.timeline-item {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  gap: 16px;
}

.timeline-rail {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #1d4ed8;
  box-shadow: 0 0 0 5px rgba(29, 78, 216, 0.1);
}

.line {
  width: 2px;
  flex: 1;
  min-height: 60px;
  margin-top: 8px;
  background: linear-gradient(180deg, #c9d8ff, transparent);
}

.timeline-card h3 {
  margin: 0;
}

.section-card__head strong,
.timeline-card__head h3 {
  line-height: 1.4;
}

.empty-wrap {
  padding: 48px 12px;
}

@media (max-width: 992px) {
  .search-box,
  .access-layout,
  .access-meta,
  .kv-grid {
    grid-template-columns: 1fr;
  }
}
</style>
