<template>
  <main class="public-page">
    <section class="query-panel">
      <div class="heading">
        <p>电子证书查询</p>
        <h1>培训结业证书查询</h1>
      </div>

      <el-form label-position="top">
        <el-form-item label="查询方式">
          <el-segmented v-model="queryMode" :options="queryOptions" />
        </el-form-item>
        <el-form-item v-if="queryMode === 'certificate'" label="证书编号">
          <el-input v-model.trim="form.certificateNo" placeholder="例如 PX2026-DBY-K7M9Q2R-83" />
        </el-form-item>
        <el-form-item v-else label="手机号">
          <el-input v-model.trim="form.phone" placeholder="请输入证书对应手机号" />
        </el-form-item>
        <el-form-item label="姓名">
          <el-input v-model.trim="form.name" placeholder="请输入证书对应姓名" />
        </el-form-item>
        <el-form-item label="图形验证码">
          <div class="captcha-row">
            <el-input v-model.trim="form.captcha" placeholder="请输入验证码" />
            <button class="captcha-button" type="button" @click="loadCaptcha">
              <img v-if="captchaImage" :src="captchaImage" alt="验证码" />
              <span v-else>刷新</span>
            </button>
          </div>
        </el-form-item>
        <el-button type="primary" class="submit" :loading="loading" @click="submitQuery">查询</el-button>
      </el-form>

      <el-alert v-if="message" class="notice" :title="message" :type="messageType" :closable="false" />

      <section v-if="results.length" class="results">
        <div class="results-head">
          <div>
            <h2>查询结果</h2>
            <p>共找到 {{ results.length }} 张证书</p>
          </div>
        </div>

        <article v-for="item in results" :key="item.certificate_no" class="certificate-card">
          <div class="card-top">
            <div>
              <span :class="['status', item.status === 'valid' ? 'ok' : 'bad']">{{ statusText(item.status) }}</span>
              <h3>{{ item.certificate_name }}</h3>
            </div>
            <p class="number">{{ item.certificate_no }}</p>
          </div>

          <dl class="meta">
            <div>
              <dt>学员姓名</dt>
              <dd>{{ item.learner_name }}</dd>
            </div>
            <div>
              <dt>项目代码</dt>
              <dd>{{ item.project_code }}</dd>
            </div>
            <div>
              <dt>课程/阶段</dt>
              <dd>{{ courseText(item) }}</dd>
            </div>
            <div>
              <dt>发证日期</dt>
              <dd>{{ item.issue_date }}</dd>
            </div>
            <div>
              <dt>发证单位</dt>
              <dd>{{ item.issuer_name }}</dd>
            </div>
          </dl>

          <div class="card-actions">
            <el-button @click="preview(item)">预览</el-button>
            <el-button type="primary" :disabled="!item.can_download_pdf" @click="downloadPdf(item)">下载 PDF</el-button>
          </div>
        </article>
      </section>

      <p class="disclaimer">
        本证书仅用于证明学员完成相关培训课程/阶段学习，不代表国家学历、学位、职业资格或职业技能等级认证。
      </p>
    </section>

    <el-dialog v-model="previewVisible" title="证书预览" width="720px" @closed="clearPreviewUrl">
      <div v-if="previewPdfUrl" class="pdf-frame">
        <embed :src="previewPdfUrl" type="application/pdf" />
      </div>
      <div v-else-if="current" class="preview-card">
        <p class="preview-kicker">Training Completion Certificate</p>
        <h2>{{ current.certificate_name }}</h2>
        <p class="preview-name">{{ current.learner_name }}</p>
        <p class="preview-copy">
          已完成 {{ current.course_name || current.project_code }} {{ current.stage_name || "" }} 相关培训学习。
        </p>
        <div class="preview-meta">
          <span>证书编号：{{ current.certificate_no }}</span>
          <span>发证日期：{{ current.issue_date }}</span>
          <span>发证单位：{{ current.issuer_name }}</span>
        </div>
      </div>
      <template #footer>
        <el-button @click="closePreview">关闭</el-button>
        <el-button v-if="current?.can_download_pdf" type="primary" @click="downloadPdf(current)">下载 PDF</el-button>
      </template>
    </el-dialog>
  </main>
</template>

<script setup lang="ts">
import { onMounted, reactive, ref, watch } from "vue";

import { http, type Captcha, type PublicCertificate } from "../api";

interface SearchResponse {
  items: PublicCertificate[];
}

const queryOptions = [
  { label: "证书编号查询", value: "certificate" },
  { label: "手机号查询", value: "phone" },
];

const queryMode = ref<"certificate" | "phone">("certificate");
const form = reactive({ certificateNo: "", phone: "", name: "", captcha: "" });
const captchaId = ref("");
const captchaImage = ref("");
const loading = ref(false);
const message = ref("");
const messageType = ref<"success" | "warning" | "error">("warning");
const results = ref<PublicCertificate[]>([]);
const previewVisible = ref(false);
const current = ref<PublicCertificate | null>(null);
const previewPdfUrl = ref("");

function statusText(status: string) {
  return status === "valid" ? "有效" : "已作废";
}

function courseText(item: PublicCertificate) {
  return [item.course_name, item.stage_name].filter(Boolean).join(" / ") || "-";
}

watch(queryMode, () => {
  message.value = "";
  results.value = [];
});

async function loadCaptcha() {
  const { data } = await http.get<Captcha>("/public/captcha");
  captchaId.value = data.captcha_id;
  captchaImage.value = data.image;
  form.captcha = "";
}

async function submitQuery() {
  loading.value = true;
  message.value = "";
  results.value = [];
  try {
    const { data } = await http.post<SearchResponse>("/public/certificates/search", {
      certificate_no: queryMode.value === "certificate" ? form.certificateNo : null,
      phone: queryMode.value === "phone" ? form.phone : null,
      name: form.name,
      captcha_id: captchaId.value,
      captcha_code: form.captcha,
    });
    results.value = data.items;
    const hasVoided = data.items.some((item) => item.status !== "valid");
    message.value = hasVoided ? "已查询到证书，其中包含作废证书，请核对状态。" : "已查询到匹配证书。";
    messageType.value = hasVoided ? "warning" : "success";
  } catch (error: any) {
    message.value = error?.response?.data?.detail || "查询失败，请稍后再试";
    messageType.value = "error";
    await loadCaptcha();
  } finally {
    loading.value = false;
  }
}

async function preview(item: PublicCertificate) {
  current.value = item;
  clearPreviewUrl();
  if (item.can_download_pdf && item.download_url) {
    const url = item.download_url.replace(/^\/api/, "");
    const { data } = await http.get(url, { responseType: "blob" });
    previewPdfUrl.value = URL.createObjectURL(data);
  }
  previewVisible.value = true;
}

function clearPreviewUrl() {
  if (previewPdfUrl.value) {
    URL.revokeObjectURL(previewPdfUrl.value);
    previewPdfUrl.value = "";
  }
}

function closePreview() {
  previewVisible.value = false;
}

function downloadPdf(item: PublicCertificate) {
  if (item.download_url) window.location.href = item.download_url;
}

onMounted(loadCaptcha);
</script>

<style scoped>
.public-page {
  min-height: 100vh;
  display: grid;
  place-items: start center;
  background: linear-gradient(180deg, #f7fafb 0%, #eef4f6 100%);
  padding: 42px 20px;
}

.query-panel {
  width: min(820px, 100%);
  background: #ffffff;
  border: 1px solid #dbe6ea;
  border-radius: 14px;
  padding: 32px;
  box-shadow: 0 18px 48px rgba(42, 64, 78, 0.09);
}

.heading {
  margin-bottom: 22px;
}

.heading p {
  margin: 0 0 6px;
  color: #16817e;
  font-size: 13px;
  font-weight: 700;
}

h1,
h2,
h3 {
  margin: 0;
}

h1 {
  font-size: 30px;
  color: #172033;
  letter-spacing: 0;
}

.captcha-row {
  display: grid;
  grid-template-columns: 1fr 132px;
  gap: 10px;
  width: 100%;
}

.captcha-button {
  height: 34px;
  padding: 0;
  border: 1px solid #dbe6ea;
  border-radius: 8px;
  background: #ffffff;
  cursor: pointer;
  overflow: hidden;
}

.captcha-button img {
  width: 100%;
  height: 100%;
  display: block;
}

.submit {
  width: 100%;
  height: 38px;
  font-weight: 700;
}

.notice,
.results {
  margin-top: 20px;
}

.results-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.results-head p {
  margin: 4px 0 0;
  color: #64748b;
  font-size: 13px;
}

.certificate-card {
  border: 1px solid #dbe6ea;
  border-radius: 10px;
  padding: 20px;
  margin-bottom: 14px;
  background: linear-gradient(180deg, #ffffff, #f8fbfc);
  box-shadow: 0 8px 22px rgba(42, 64, 78, 0.05);
}

.card-top {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  align-items: flex-start;
  padding-bottom: 14px;
  border-bottom: 1px solid #e8eef1;
}

.status {
  display: inline-flex;
  height: 24px;
  align-items: center;
  border-radius: 999px;
  padding: 0 9px;
  margin-bottom: 10px;
  font-size: 12px;
}

.status.ok {
  color: #0f6f6b;
  background: #e6f5f3;
}

.status.bad {
  color: #991b1b;
  background: #fee2e2;
}

.number {
  margin: 0;
  color: #475569;
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 13px;
  padding-top: 4px;
}

.meta {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px 22px;
  margin: 16px 0;
}

.meta div {
  min-width: 0;
}

.meta dt {
  color: #64748b;
  font-size: 12px;
  font-weight: 650;
  margin-bottom: 4px;
}

.meta dd {
  margin: 0;
  color: #172033;
  font-size: 14px;
}

.card-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.disclaimer {
  margin: 20px 0 0;
  color: #6b7280;
  font-size: 13px;
  line-height: 1.6;
  padding-top: 16px;
  border-top: 1px solid #e8eef1;
}

.preview-card {
  border: 1px solid #dfe9ec;
  border-radius: 10px;
  padding: 32px;
  text-align: center;
  background: linear-gradient(180deg, #ffffff, #f8fbfc);
}

.pdf-frame {
  height: 70vh;
  border: 1px solid #dfe9ec;
  border-radius: 10px;
  overflow: hidden;
  background: #f8fafc;
}

.pdf-frame embed {
  width: 100%;
  height: 100%;
}

.preview-kicker {
  margin: 0 0 10px;
  color: #16817e;
  font-size: 12px;
  letter-spacing: 0;
  text-transform: uppercase;
}

.preview-name {
  margin: 22px 0 10px;
  font-size: 28px;
  font-weight: 700;
}

.preview-copy {
  margin: 0 auto 24px;
  max-width: 520px;
  color: #475569;
  line-height: 1.8;
}

.preview-meta {
  display: grid;
  gap: 8px;
  color: #64748b;
  font-size: 13px;
}

@media (max-width: 640px) {
  .query-panel {
    padding: 22px;
  }

  .card-top,
  .card-actions {
    display: grid;
    justify-content: stretch;
  }

  .meta {
    grid-template-columns: 1fr;
  }
}
</style>
