<!-- SPEC: HWPOD Node Python 单文件接入与 readiness. -->
<!-- Responsibility: 用户自行下载、校验、启动 Python 单文件节点，并观察分阶段接入状态。 -->

<script setup lang="ts">
import HwpodReadinessRail from "./HwpodReadinessRail.vue";
import type {
  HwlabNodeUpdateMetadata,
  HwpodNodeReadinessStage,
  HwpodNodeTopologyItem,
} from "@/types";

defineProps<{
  metadata: HwlabNodeUpdateMetadata | null;
  nodes: HwpodNodeTopologyItem[];
  selectedNodeId: string;
  stages: HwpodNodeReadinessStage[];
  copied: boolean;
}>();

const emit = defineEmits<{ copy: []; node: [nodeId: string] }>();
const statusLabel = (status: string): string =>
  ({
    online: "在线",
    offline: "离线",
    busy: "忙碌",
    available: "可用",
    error: "异常",
  })[status] || status || "unknown";
const formatSize = (value: number): string =>
  value > 1024 * 1024
    ? `${(value / 1024 / 1024).toFixed(1)} MiB`
    : `${Math.ceil(value / 1024)} KiB`;
</script>

<template>
  <section class="onboarding-grid">
    <article class="artifact-panel">
      <span class="panel-kicker">Python single file</span>
      <h2>{{ metadata?.artifact.fileName || "hwlab-node.py" }}</h2>
      <p>
        由用户在自己的 Windows 交互会话中下载并运行 Python 单文件节点。节点主动出站连接 Cloud API；下载完成不代表 HWPOD 已 ready。
      </p>
      <dl>
        <div><dt>版本</dt><dd>{{ metadata?.artifact.version || "-" }}</dd></div>
        <div><dt>大小</dt><dd>{{ formatSize(metadata?.artifact.sizeBytes || 0) }}</dd></div>
        <div class="sha-row">
          <dt>SHA-256</dt>
          <dd>
            <code>{{ metadata?.artifact.sha256 || "未发布" }}</code>
            <button
              type="button"
              :disabled="!metadata?.artifact.sha256"
              @click="emit('copy')"
            >
              {{ copied ? "已复制" : "复制" }}
            </button>
          </dd>
        </div>
      </dl>
      <a
        v-if="metadata?.artifact.downloadUrl"
        class="download-button"
        :href="metadata.artifact.downloadUrl"
        :download="metadata.artifact.fileName"
      >下载 Python 单文件</a>
      <p v-else class="download-blocked">发布 artifact 当前不可用。</p>

      <details class="release-disclosure">
        <summary>版本与发布说明</summary>
        <ul>
          <li v-for="note in metadata?.releaseNotes || []" :key="note">{{ note }}</li>
          <li v-if="!metadata?.releaseNotes?.length">当前版本未提供额外发布说明。</li>
        </ul>
      </details>
      <details class="release-disclosure">
        <summary>安装条件</summary>
        <ul>
          <li
            v-for="condition in metadata?.installConditions || []"
            :key="condition.id"
          >
            {{ condition.required ? "必须" : "建议" }} · {{ condition.label }}
          </li>
          <li v-if="!metadata?.installConditions?.length">请确认本机 Python 3 与 tkinter 可用。</li>
        </ul>
      </details>
    </article>

    <article class="install-panel">
      <span class="panel-kicker">Self-service install</span>
      <h2>用户自行安装步骤</h2>
      <ol class="install-steps">
        <li>
          <strong>下载并固定文件</strong>
          <p>将单文件保存到 owning YAML 允许的用户可写目录，不要从浏览器临时目录长期运行。</p>
          <details>
            <summary>查看配置边界</summary>
            <span>实际运行目录、交互用户和工作区根由 owning YAML 与受控节点配置拥有，网页不猜测目标路径。</span>
          </details>
        </li>
        <li>
          <strong>校验 SHA-256</strong>
          <p>将本机结果与页面上方发布 SHA 完整比对，不一致时停止运行并重新下载。</p>
          <details>
            <summary>查看 PowerShell 命令</summary>
            <code>Get-FileHash .\{{ metadata?.artifact.fileName || "hwlab-node.py" }} -Algorithm SHA256</code>
          </details>
        </li>
        <li>
          <strong>在交互用户会话启动</strong>
          <p>使用 owning YAML 选择的 Windows 交互用户与原生 Python 启动图形节点，保持窗口或托盘程序运行。</p>
          <details>
            <summary>查看启动命令</summary>
            <code>python .\{{ metadata?.artifact.fileName || "hwlab-node.py" }}</code>
            <span>在已选定的安装目录中执行；不得使用 WSL Python、SSH 辅助解释器、Bun 运行器或非交互 Windows 服务。</span>
          </details>
        </li>
        <li>
          <strong>选择 Node 并观察 readiness</strong>
          <p>节点上线后在下方选择对应 Node，逐项确认连接、工作区和 HWPOD 挂载阶段。</p>
          <details open>
            <summary>当前状态</summary>
            <span>{{ selectedNodeId ? "已选择 Node，可核对阶段状态。" : "尚未选择已连接 Node。" }}</span>
          </details>
        </li>
      </ol>
    </article>

    <article class="readiness-panel">
      <header>
        <div><span class="panel-kicker">Staged readiness</span><h2>接入进度</h2></div>
        <label>
          Node
          <select
            :value="selectedNodeId"
            @change="emit('node', ($event.target as HTMLSelectElement).value)"
          >
            <option value="">未选择</option>
            <option v-for="node in nodes" :key="node.nodeId" :value="node.nodeId">
              {{ node.name }} · {{ statusLabel(node.status) }}
            </option>
          </select>
        </label>
      </header>
      <HwpodReadinessRail :stages="stages" />
      <aside class="outbound-note">
        <strong>网络边界</strong>
        <span>节点只使用主动出站 WebSocket。网页不生成凭据，不要求用户 PC 开放入站端口。</span>
      </aside>
    </article>
  </section>
</template>

<style scoped>
.onboarding-grid { display: grid; grid-template-columns: minmax(0, .85fr) minmax(0, 1fr); gap: 16px; }
.artifact-panel, .install-panel, .readiness-panel { min-width: 0; padding: 18px; border: 1px solid #c1cbc7; border-top: 3px solid #3a766a; border-radius: 8px; background: #fbfaf6; box-shadow: 0 10px 26px rgb(19 42 36 / 7%); }
.readiness-panel { grid-column: 1 / -1; }
.panel-kicker { color: #397166; font: 800 .66rem ui-monospace, SFMono-Regular, Consolas, monospace; text-transform: uppercase; }
h2 { margin: 5px 0 9px; color: #1e342e; font-size: 1.08rem; }
.artifact-panel > p, .install-panel > p { color: #61706b; line-height: 1.55; }
dl { display: grid; gap: 8px; margin: 16px 0; }
dl > div { min-width: 0; padding: 9px 10px; border: 1px solid #d6dedb; border-radius: 6px; background: #f3f7f4; }
dt { color: #6d7a75; font-size: .68rem; font-weight: 800; text-transform: uppercase; }
dd { margin: 3px 0 0; overflow-wrap: anywhere; }
.sha-row dd { display: flex; gap: 8px; align-items: center; }
.sha-row code { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sha-row button { margin-left: auto; flex: 0 0 auto; border: 1px solid #b8c5c0; border-radius: 5px; background: #fff; padding: 4px 7px; cursor: pointer; }
.download-button { display: flex; justify-content: center; padding: 11px 14px; border-radius: 7px; background: #173e35; color: #f5fcf9; font-weight: 800; text-decoration: none; }
.download-blocked { padding: 10px; border: 1px solid #ddafa7; background: #fff0ed; color: #7b332c; }
.release-disclosure, .install-steps details { margin-top: 10px; border: 1px solid #d5ddda; border-radius: 6px; background: #f5f8f6; }
.release-disclosure summary, .install-steps summary { padding: 9px 10px; color: #31564d; font-size: .75rem; font-weight: 800; cursor: pointer; }
.release-disclosure ul { margin: 0; padding: 0 28px 12px; color: #5f6d68; font-size: .76rem; line-height: 1.6; }
.install-steps { display: grid; gap: 12px; margin: 14px 0 0; padding: 0; counter-reset: install-step; list-style: none; }
.install-steps > li { position: relative; padding: 12px 12px 12px 46px; border-left: 3px solid #3a766a; background: #f2f7f4; counter-increment: install-step; }
.install-steps > li::before { position: absolute; top: 11px; left: 12px; display: grid; width: 23px; height: 23px; place-items: center; border-radius: 50%; background: #245f54; color: #fff; content: counter(install-step); font: 800 .72rem ui-monospace, monospace; }
.install-steps strong { color: #203c35; font-size: .83rem; }
.install-steps p { margin: 5px 0 0; color: #61706b; font-size: .76rem; line-height: 1.5; }
.install-steps details code, .install-steps details span { display: block; margin: 0 10px 8px; overflow: auto; color: #29483f; font-size: .72rem; white-space: nowrap; }
.readiness-panel > header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.readiness-panel label { display: grid; gap: 4px; color: #6b7873; font-size: .68rem; font-weight: 800; text-transform: uppercase; }
.readiness-panel select { max-width: 260px; border: 1px solid #b5c1bd; border-radius: 6px; background: #fff; padding: 7px 9px; color: #263c36; }
.outbound-note { display: grid; gap: 5px; margin-top: 14px; padding: 12px; border-left: 3px solid #398477; background: #eaf6f1; color: #365d54; font-size: .77rem; line-height: 1.45; }
@media (max-width: 1100px) { .onboarding-grid { grid-template-columns: 1fr; } .readiness-panel { grid-column: auto; } }
@media (max-width: 680px) { .readiness-panel > header { flex-direction: column; } .readiness-panel select { max-width: 100%; } }
</style>
