<template>
  <main class="public-query-page">
    <PublicServiceHeader />

    <section class="query-main">
      <header class="query-intro">
        <p class="eyebrow">CERTIFICATE VERIFICATION</p>
        <h1>证书查询与核验</h1>
        <p class="intro-copy">查询慧遇书院已签发的培训结业证书</p>
        <div class="trust-row">
          <span><el-icon><CircleCheck /></el-icon>签发记录可追溯</span>
          <span><el-icon><Lock /></el-icon>查询信息安全保护</span>
        </div>
      </header>

      <section class="query-card" aria-label="证书查询表单">
        <div class="query-card-head">
          <div>
            <h2>查询证书</h2>
            <p>请选择证书编号或短信验证码查询</p>
          </div>
          <span class="official-mark"><img src="/brand/huiyu-logo.png" alt="" />官方查询</span>
        </div>

        <el-form label-position="top" size="large">
        <el-form-item label="查询方式">
          <el-segmented v-model="queryMode" :options="queryOptions" class="query-mode" />
        </el-form-item>
        <el-form-item v-if="queryMode === 'certificate'" label="证书编号">
          <el-input v-model.trim="form.certificateNo" placeholder="例如 PX2026-DBY-K7M9Q2R-83">
            <template #prefix><el-icon><Postcard /></el-icon></template>
          </el-input>
        </el-form-item>
        <el-form-item v-if="queryMode === 'certificate'" label="姓名">
          <el-input v-model.trim="form.name" placeholder="请输入证书对应姓名">
            <template #prefix><el-icon><User /></el-icon></template>
          </el-input>
        </el-form-item>
        <el-form-item v-if="queryMode === 'certificate'" label="图形验证码">
          <div class="captcha-row">
            <el-input v-model.trim="form.captcha" placeholder="请输入验证码">
              <template #prefix><el-icon><Key /></el-icon></template>
            </el-input>
            <button class="captcha-button" type="button" title="点击刷新验证码" @click="loadCaptcha">
              <img v-if="captchaImage" :src="captchaImage" alt="验证码" />
              <span v-else><el-icon><RefreshRight /></el-icon>刷新</span>
            </button>
          </div>
        </el-form-item>
        <el-form-item v-if="queryMode === 'sms'" label="手机号">
          <el-input v-model.trim="form.phone" placeholder="请输入证书对应手机号">
            <template #prefix><el-icon><Phone /></el-icon></template>
          </el-input>
        </el-form-item>
        <el-form-item v-if="queryMode === 'sms'" label="图形验证码">
          <div class="captcha-row">
            <el-input v-model.trim="form.smsCaptcha" placeholder="请输入验证码">
              <template #prefix><el-icon><Key /></el-icon></template>
            </el-input>
            <button class="captcha-button" type="button" title="点击刷新验证码" @click="loadSmsCaptcha">
              <img v-if="smsCaptchaImage" :src="smsCaptchaImage" alt="验证码" />
              <span v-else><el-icon><RefreshRight /></el-icon>刷新</span>
            </button>
          </div>
        </el-form-item>
        <el-form-item v-if="queryMode === 'sms'" label="短信验证码">
          <div class="sms-row">
            <el-input v-model.trim="form.smsCode" placeholder="请输入短信验证码">
              <template #prefix><el-icon><Message /></el-icon></template>
            </el-input>
            <el-button 
              type="primary" 
              :disabled="smsCooldown > 0 || !form.phone" 
              @click="sendSmsCode"
              :loading="sendingSms"
            >
              {{ smsCooldown > 0 ? `${smsCooldown}秒后重试` : '获取验证码' }}
            </el-button>
          </div>
        </el-form-item>
        <el-button type="primary" class="submit" :icon="Search" :loading="loading" @click="submitQuery">查询证书</el-button>
      </el-form>

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

      <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>
          </dl>

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

    </section>

    <footer class="public-footer">
      <p>本证书仅用于证明学员完成相关培训课程或阶段学习，不代表国家学历、学位、职业资格或职业技能等级认证。</p>
      <span>慧遇书院电子证书服务</span>
    </footer>

    <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="previewLoading" class="pdf-loading">
        <el-icon class="is-loading"><Loading /></el-icon>
        <p>当前查询人数较多，请稍后。。。</p>
      </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>
        </div>
      </div>
      <template #footer>
        <el-button @click="closePreview">关闭</el-button>
        <el-button
          v-if="current?.can_download_pdf"
          type="primary"
          :loading="downloadingCertificateNo === current.certificate_no"
          @click="downloadPdf(current)"
        >
          下载 PDF
        </el-button>
      </template>
    </el-dialog>
  </main>
</template>

<script setup lang="ts">
import {
  CircleCheck,
  Download,
  Key,
  Loading,
  Lock,
  Message,
  Phone,
  Postcard,
  RefreshRight,
  Search,
  User,
  View,
} from "@element-plus/icons-vue";
import { ElLoading, ElMessage } from "element-plus";
import { onMounted, onUnmounted, reactive, ref, watch } from "vue";

import { http, type Captcha, type PublicCertificate } from "../api";
import { apiErrorMessage, saveBlob } from "../download";
import PublicServiceHeader from "../components/PublicServiceHeader.vue";

interface SearchResponse {
  items: PublicCertificate[];
}

const queryOptions = [
  { label: "证书编号查询", value: "certificate" },
  { label: "短信验证码查询", value: "sms" },
];

const queryMode = ref<"certificate" | "sms">("certificate");
const form = reactive({ certificateNo: "", phone: "", name: "", captcha: "", smsCaptcha: "", smsCode: "" });
const captchaId = ref("");
const captchaImage = ref("");
const smsCaptchaId = ref("");
const smsCaptchaImage = 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("");
const previewLoading = ref(false);
const downloadingCertificateNo = ref("");
const smsId = ref("");
const sendingSms = ref(false);
const smsCooldown = ref(0);
let smsTimer: number | null = null;

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 = [];
  if (queryMode.value === "sms") {
    loadSmsCaptcha();
  }
});

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

async function loadSmsCaptcha() {
  const { data } = await http.get<Captcha>("/public/captcha");
  smsCaptchaId.value = data.captcha_id;
  smsCaptchaImage.value = data.image;
  form.smsCaptcha = "";
}

async function sendSmsCode() {
  if (!form.phone) {
    message.value = "请先输入手机号";
    messageType.value = "warning";
    return;
  }
  
  sendingSms.value = true;
  message.value = "";
  
  try {
    const { data } = await http.post<{ sms_id: string; message: string }>("/public/sms/send", {
      phone: form.phone,
      captcha_id: smsCaptchaId.value,
      captcha_code: form.smsCaptcha,
    });
    smsId.value = data.sms_id;
    message.value = data.message;
    messageType.value = "success";
    
    // 开始倒计时
    smsCooldown.value = 60;
    if (smsTimer) clearInterval(smsTimer);
    smsTimer = window.setInterval(() => {
      smsCooldown.value--;
      if (smsCooldown.value <= 0) {
        if (smsTimer) clearInterval(smsTimer);
        smsTimer = null;
      }
    }, 1000);
  } catch (error: any) {
    message.value = error?.response?.data?.detail || "发送失败，请稍后再试";
    messageType.value = "error";
    await loadSmsCaptcha();
  } finally {
    sendingSms.value = false;
  }
}

async function submitQuery() {
  loading.value = true;
  message.value = "";
  results.value = [];
  
  try {
    let data: SearchResponse;
    
    if (queryMode.value === "certificate") {
      // 证书编号查询
      const response = await http.post<SearchResponse>("/public/certificates/search", {
        certificate_no: form.certificateNo,
        phone: null,
        name: form.name,
        captcha_id: captchaId.value,
        captcha_code: form.captcha,
      });
      data = response.data;
    } else {
      // 短信验证码查询
      if (!smsId.value) {
        message.value = "请先获取短信验证码";
        messageType.value = "warning";
        return;
      }
      
      const response = await http.post<SearchResponse>("/public/certificates/search-by-sms", {
        phone: form.phone,
        sms_id: smsId.value,
        sms_code: form.smsCode,
      });
      data = response.data;
    }
    
    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";
    if (queryMode.value === "certificate") {
      await loadCaptcha();
    }
  } finally {
    loading.value = false;
  }
}

async function preview(item: PublicCertificate) {
  current.value = item;
  clearPreviewUrl();
  previewVisible.value = true;
  if (item.can_download_pdf && item.download_url) {
    previewLoading.value = true;
    try {
      const url = item.download_url.replace(/^\/api/, "");
      const { data } = await http.get(url, { responseType: "blob" });
      previewPdfUrl.value = URL.createObjectURL(data);
    } catch (error: any) {
      message.value = await apiErrorMessage(error, "PDF生成失败，请稍后再试");
      messageType.value = "error";
    } finally {
      previewLoading.value = false;
    }
  }
}

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

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

async function downloadPdf(item: PublicCertificate) {
  if (!item.download_url) return;
  downloadingCertificateNo.value = item.certificate_no;
  const loading = ElLoading.service({
    lock: true,
    text: "当前查询人数较多，请稍后。。。",
    background: "rgba(255, 255, 255, 0.72)",
  });
  try {
    const url = item.download_url.replace(/^\/api/, "");
    const { data } = await http.get(url, { responseType: "blob" });
    saveBlob(data, `${item.certificate_no}.pdf`);
  } catch (error: any) {
    ElMessage.error(await apiErrorMessage(error, "PDF生成失败，请稍后再试"));
  } finally {
    loading.close();
    downloadingCertificateNo.value = "";
  }
}

onMounted(loadCaptcha);

// 清理定时器
onUnmounted(() => {
  if (smsTimer) {
    clearInterval(smsTimer);
    smsTimer = null;
  }
});
</script>

<style scoped>
.public-query-page {
  min-height: 100vh;
  background: #f4f6f7;
}

.query-main {
  width: min(880px, calc(100% - 40px));
  margin: 0 auto;
  padding: 62px 0 48px;
}

.query-intro {
  margin-bottom: 30px;
  text-align: center;
}

.eyebrow {
  margin: 0 0 10px;
  color: #9a7637;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 12px;
  font-weight: 700;
}

h1,
h2,
h3,
.query-intro p {
  letter-spacing: 0;
}

h1,
h2,
h3 {
  margin: 0;
}

h1 {
  color: #17212b;
  font-size: 38px;
  font-weight: 720;
}

.intro-copy {
  margin: 12px 0 0;
  color: #677681;
  font-size: 15px;
}

.trust-row {
  display: flex;
  justify-content: center;
  gap: 24px;
  margin-top: 18px;
  color: #5e6d77;
  font-size: 13px;
}

.trust-row span {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

.trust-row .el-icon {
  color: #27765f;
}

.query-card {
  padding: 28px 30px 30px;
  border: 1px solid #dce3e6;
  border-top: 3px solid #b28a43;
  border-radius: 7px;
  background: #ffffff;
  box-shadow: 0 14px 36px rgba(31, 47, 57, 0.08);
}

.query-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px;
  margin-bottom: 22px;
  padding-bottom: 18px;
  border-bottom: 1px solid #edf1f2;
}

.query-card-head h2 {
  font-size: 20px;
}

.query-card-head p {
  margin: 6px 0 0;
  color: #75818a;
  font-size: 13px;
}

.official-mark {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: #87672f;
  font-size: 12px;
  font-weight: 650;
}

.official-mark img {
  width: 18px;
  height: 16px;
  object-fit: contain;
}

.query-mode {
  width: 100%;
}

:deep(.query-mode .el-segmented__group) {
  width: 100%;
}

:deep(.query-mode .el-segmented__item) {
  flex: 1;
  min-height: 38px;
}

.captcha-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 148px;
  gap: 10px;
  width: 100%;
}

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

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

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

.captcha-button span {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  color: #5f6f79;
}

.submit {
  width: 100%;
  height: 44px;
  margin-top: 4px;
  font-weight: 700;
}

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

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

.results-head h2 {
  font-size: 21px;
}

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

.certificate-card {
  border: 1px solid #dce3e6;
  border-radius: 7px;
  padding: 22px;
  margin-bottom: 12px;
  background: #ffffff;
  box-shadow: 0 4px 14px rgba(31, 47, 57, 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;
}

.preview-card {
  border: 1px solid #dfe9ec;
  border-radius: 7px;
  padding: 32px;
  text-align: center;
  background: #f8fafb;
}

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

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

.pdf-loading {
  min-height: 240px;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 12px;
  color: #64748b;
}

.pdf-loading .el-icon {
  color: #16817e;
  font-size: 28px;
}

.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;
}

.public-footer {
  width: min(880px, calc(100% - 40px));
  margin: 0 auto;
  padding: 24px 0 32px;
  border-top: 1px solid #dfe5e7;
  color: #75818a;
  font-size: 12px;
  line-height: 1.7;
  text-align: center;
}

.public-footer p {
  margin: 0;
}

.public-footer span {
  display: block;
  margin-top: 8px;
  color: #9a7637;
}

@media (max-width: 640px) {
  .query-main {
    width: calc(100% - 28px);
    padding: 38px 0 34px;
  }

  h1 {
    font-size: 30px;
  }

  .trust-row {
    display: grid;
    gap: 8px;
  }

  .query-card {
    padding: 22px 18px;
  }

  .query-card-head {
    display: grid;
  }

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

  .meta {
    grid-template-columns: 1fr;
  }

  .captcha-row,
  .sms-row {
    grid-template-columns: minmax(0, 1fr) 126px;
  }

  .card-actions .el-button {
    width: 100%;
    margin: 0;
  }
}
</style>
