#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Assemble the reviewable A5 tri-product engineering increment."""
from __future__ import annotations

import hashlib
import csv
import json
import shutil
import zipfile
from pathlib import Path

ROOT = Path(__file__).resolve().parents[2]
WORK = ROOT / "work/tri-product-continuation-2026-10-10.nosync"
CAND = WORK / "drill_motor_run_gate_r1"
DEST = ROOT / "outputs/三款千台落地增量-A5-v0.1-2026-10-10"
ZIP_PATH = ROOT / "outputs/三款千台落地增量-A5-v0.1-2026-10-10.zip"


def sha(path: Path) -> str:
    return hashlib.sha256(path.read_bytes()).hexdigest()


def copy(src: Path, rel: str) -> None:
    dst = DEST / rel
    dst.parent.mkdir(parents=True, exist_ok=True)
    shutil.copy2(src, dst)


def main() -> None:
    if DEST.exists() or ZIP_PATH.exists():
        raise SystemExit("A5 output already exists; refusing to overwrite.")

    # Product identity, sample acceptance and previous lamp safety evidence.
    copy(WORK / "工程状态增量-2026-10-10-continuation.json", "工程状态增量-2026-10-10.json")
    copy(WORK / "灯具硬件安全门控逻辑核验-r0.1.md", "灯具硬件安全门控逻辑核验-r0.1.md")
    copy(ROOT / "work/tri-product-continuation-2026-10-09.nosync/三款参考机同台A-B测试作业书-r0.3.md",
         "三款参考机同台A-B测试作业书-r0.3.md")
    copy(ROOT / "work/tri-product-continuation-2026-10-09.nosync/hardware_source_localization_v140/early_drc/hardware_layout_audit_v140.json",
         "七板基线DRC与网络比对-2026-10-09.json")
    copy(ROOT / "outputs/三款千台落地增量-A3-v0.1-2026-10-09/三款1k降本机会筛查-2026-10-09.md",
         "三款1k降本机会筛查-A3基线.md")

    # Corrected isolated motor-stage design and its receipts.
    copy(CAND / "README.md", "电磨电机板_A1_RUN_GATE/README.md")
    copy(CAND / "drill_motor/drill_motor.kicad_sch", "电磨电机板_A1_RUN_GATE/drill_motor.kicad_sch")
    copy(CAND / "drill_motor/evt/drill_motor_evt_a1_run_gate.kicad_pcb",
         "电磨电机板_A1_RUN_GATE/evt/drill_motor_evt_a1_run_gate.kicad_pcb")
    copy(CAND / "drill_motor/evt/drill_motor_evt_a1_run_gate.kicad_pro",
         "电磨电机板_A1_RUN_GATE/evt/drill_motor_evt_a1_run_gate.kicad_pro")
    copy(CAND / "drill_motor/evt/fp-lib-table", "电磨电机板_A1_RUN_GATE/evt/fp-lib-table")
    copy(CAND / "drill_motor/evt/MotorStage.pretty/TI_RGF0040E_VQFN-40-1EP_7x5mm_P0.5mm.kicad_mod",
         "电磨电机板_A1_RUN_GATE/evt/MotorStage.pretty/TI_RGF0040E_VQFN-40-1EP_7x5mm_P0.5mm.kicad_mod")
    copy(CAND / "drill_motor/evt/drill_motor_evt_a0.kicad_pcb",
         "电磨电机板_A1_RUN_GATE/evt/drill_motor_evt_a0.kicad_pcb")
    copy(CAND / "drill_motor/evt/drill_motor_evt_a0.kicad_pro",
         "电磨电机板_A1_RUN_GATE/evt/drill_motor_evt_a0.kicad_pro")
    for name in [
        "candidate_manifest.json",
        "BOM_motor_RUN_GATE_A1_candidate.csv",
        "BOM_motor_RUN_GATE_A1_delta_1000pcs.csv",
        "drill_motor_run_gate_r1.validation.json",
        "drill_motor_run_gate_r1.net.xml",
        "drill_motor_run_gate_r1.net_parity.json",
        "drill_motor_run_gate_r1.drc.rpt",
        "drill_motor_run_gate_r1.erc.rpt",
    ]:
        copy(CAND / name, f"电磨电机板_A1_RUN_GATE/验证与BOM/{name}")
    copy(WORK / "电磨电机板-DRVOFF关断修订与1k成本增量核验-r0.1.md",
         "电磨电机板-DRVOFF关断修订与1k成本增量核验-r0.1.md")
    copy(WORK / "drill_motor_candidate_a1.pdf", "电磨电机板_A1_RUN_GATE/可视化/drill_motor_candidate_a1.pdf")
    copy(WORK / "drill_motor_candidate_a1_page_1.png",
         "电磨电机板_A1_RUN_GATE/可视化/drill_motor_candidate_a1_page_1.png")
    copy(WORK / "build_drill_motor_run_gate_r1.py", "tools/build_drill_motor_run_gate_r1.py")
    copy(WORK / "finalize_drill_motor_run_gate_r1.py", "tools/finalize_drill_motor_run_gate_r1.py")

    # Fresh target-image build receipts. Output-enable and physical states remain disabled/unverified.
    copy(WORK / "firmware_target_build_r1/lamp/build_verification.json",
         "固件静态重建/lamp_target_build_verification.json")
    copy(WORK / "firmware_target_build_r1/drill/build_verification.json",
         "固件静态重建/drill_target_build_verification.json")
    copy(WORK / "firmware_v140_patch_r1/目标板构建校验.json",
         "固件静态重建/vacuum_target_v1.40_build_verification.json")
    firmware_checks = json.loads((CAND / "drill_motor_run_gate_r1.validation.json").read_text(encoding="utf-8"))
    (DEST / "固件静态重建/主机回归与目标镜像边界.json").write_text(
        json.dumps({
            "host_regressions": firmware_checks["host_regressions"],
            "target_builds": firmware_checks["firmware_target_builds"],
            "note": "Static build receipts only. Motor, LED and vacuum outputs remain disabled or physically unverified; these are not production images.",
        }, ensure_ascii=False, indent=2) + "\n",
        encoding="utf-8",
    )

    # Preserve only the relevant low-cost material benchmark and disclose its scope.
    r9 = json.loads((ROOT / "work/tri-product-continuation-2026-10-09.nosync/factory_quote_inputs_v140/passive_mpn_candidates_r4/supplier_rfq_pack_r9_costdown_capacitors/08_低成本被动件候选r4映射与限制.json").read_text(encoding="utf-8"))
    cost_subset = {
        "source": "R9 catalog-price benchmark; component-material subset only",
        "source_file": "factory_quote_inputs_v140/passive_mpn_candidates_r4/.../08_低成本被动件候选r4映射与限制.json",
        "source_sha256": sha(ROOT / "work/tri-product-continuation-2026-10-09.nosync/factory_quote_inputs_v140/passive_mpn_candidates_r4/supplier_rfq_pack_r9_costdown_capacitors/08_低成本被动件候选r4映射与限制.json"),
        "catalog_material_benchmark_r9": r9["catalog_material_benchmark_r9"],
        "candidate_r15": {
            "added_per_drill_unit": 1,
            "quantity_for_1000_drills": 1000,
            "mpn_candidate": "RC0603FR-0710KL",
            "public_catalog_unit_price_usd_at_1000_plus": 0.0026,
            "public_catalog_extended_price_usd_at_1000": 2.60,
            "source": "LCSC C98220; accessed 2026-10-10; https://www.lcsc.com/product-detail/C98220.html",
            "formal_factory_quote": False,
            "included_in_r9_subtotal": False,
            "status": "RFQ candidate; no formal quote or AVL freeze",
        },
        "passive_subset_with_r15": {
            "drill_per_unit_usd": 0.1767,
            "drill_1000_units_usd": 176.70,
            "dust_collector_1000_units_usd": 24.60,
            "lamp_1000_units_usd": 203.20,
            "three_runs_subtotal_usd": 404.50,
            "scope_warning": "Selected passive-component subset only; not complete BOM, PCBA or finished product cost.",
        },
        "freight": "Not estimated per user instruction",
        "full_pcba_or_finished_product_cost": "Not quoted",
    }
    (DEST / "成本口径").mkdir(parents=True, exist_ok=True)
    (DEST / "成本口径/1k目录价与新增R15成本边界.json").write_text(
        json.dumps(cost_subset, ensure_ascii=False, indent=2) + "\n",
        encoding="utf-8",
    )
    quote_source = ROOT / "outputs/三款千台落地增量-A2-v0.2-2026-10-09/工厂询价回填.csv"
    with quote_source.open(encoding="utf-8-sig", newline="") as stream:
        quote_reader = csv.reader(stream)
        quote_rows = list(quote_reader)
    quote_rows.append([
        "打磨机",
        "电磨电机板R15新增位号",
        "每台增加1只 YAGEO RC0603FR-0710KL（LCSC C98220），0603/10k/±1%；公开目录参考 US$0.0026/只@1000+，请按工厂采购渠道正式报价并确认二供",
        "1000",
        "",
        "",
        "",
        "",
        "",
        "",
        "待工厂回填",
        "RC0603FR-0710KL",
        "待工程批准",
        "https://www.lcsc.com/product-detail/C98220.html",
        "",
        "新增 DRVOFF 上拉；目录价不是正式报价；运费按用户要求不估算",
    ])
    quote_path = DEST / "成本口径/工厂询价回填模板_A5.csv"
    with quote_path.open("w", encoding="utf-8-sig", newline="") as stream:
        csv.writer(stream).writerows(quote_rows)

    readme = """# 三款美甲设备 PCBA 千台落地增量 A5

目标套装：Amazon B0HBWRZR4G。当前页面显示该套装包含电磨 B0GS9DGC7V、集尘器 B0H1RFPW2Y、插电 AI 光疗灯 B0GR425DGM 三件。此交付仍是工程候选和验证资料，不是制板或量产放行。

本包新增的硬件修正是电磨 DRV8316 的 DRVOFF 上拉：A0 网表缺少把 DRVOFF 拉高的器件；A1 隔离候选增加 R15=10k 1% 从 DRV_AVDD 接至 DRV_OFF。KiCad 10.0.6 DRC 为 0 violations / 0 unconnected items，原理图到 PCB 的 135 个已连接引脚网络比对通过。ERC 有 0 errors、42 条本地 Project 符号库别名未配置警告。样机上的波形、电机电流、扭矩/转速与故障停机还没有实测。

三款灯具、电磨、集尘器目标固件的本地静态镜像均重新构建通过，v1.39 全量 23 个主机测试和 v1.40 集尘器增量 20 个主机测试通过。它们仍是安全引导/输出锁定状态：灯珠输出和电机输出未启用；集尘器风机电源/PWM 由硬锁保持关闭。不能把静态构建当作产品运行验证。

降本按每款 1,000 台估算。R15 令电磨候选 BOM 增加 1,000 只 0603/10k/1% 电阻，复用现有询价候选 MPN RC0603FR-0710KL。LCSC 当前 1,000+ 阶梯目录价快照为 US$0.0026/只，页面当日显示约 5,990,700 只库存；新增位号算术小计约 US$2.60/1,000 台，价格和库存会变化，这不是正式工厂报价或可锁定采购价。计入 R15 后，三款被动件目录价子集合计约 US$404.50，不是完整 BOM/整机成本。运费按用户要求不估算。

随包的 A/B 作业书 r0.3 规定了参考机和每款 3 台候选样机的筛选方法。当前所有实体样机比较均为 NOT_RUN_NO_SAMPLE；测试由用户方工程师或工厂接收样机后执行。此包不含供应商报价、不代表 DFM/认证/可靠性审核，也没有授权投板或量产。

核心文件：

- 电磨原理图/PCB：电磨电机板_A1_RUN_GATE/
- 电磨审查记录：电磨电机板-DRVOFF关断修订与1k成本增量核验-r0.1.md
- 三款安全与性能测试：三款参考机同台A-B测试作业书-r0.3.md
- 灯具硬件门控审查：灯具硬件安全门控逻辑核验-r0.1.md
- 成本口径：成本口径/1k目录价与新增R15成本边界.json
- 全机成本回填：成本口径/工厂询价回填模板_A5.csv（保留PCBA、电池/风机/电源、结构、测试和MOQ等完整询价行，并加上R15）

建议工厂打样前先确认 R15 焊接/丝印、DRV8316 供电启动和 DRVOFF 默认关断，再按 A/B 作业书逐步进行限流台架测试。样机结果返回后再评估闭环转速、限流值、器件替代和整机成本冻结。
"""
    (DEST / "README.md").write_text(readme, encoding="utf-8")

    # Hash every deliverable file except the manifest itself, then create a portable zip.
    entries = []
    for path in sorted(p for p in DEST.rglob("*") if p.is_file()):
        rel = path.relative_to(DEST).as_posix()
        entries.append(f"{sha(path)}  {rel}")
    (DEST / "MANIFEST-SHA256.txt").write_text("\n".join(entries) + "\n", encoding="utf-8")
    with zipfile.ZipFile(ZIP_PATH, "w", compression=zipfile.ZIP_DEFLATED, compresslevel=9) as zf:
        for path in sorted(p for p in DEST.rglob("*") if p.is_file()):
            zf.write(path, path.relative_to(DEST).as_posix())
    with zipfile.ZipFile(ZIP_PATH) as zf:
        bad = zf.testzip()
        if bad:
            raise RuntimeError(f"ZIP CRC failure: {bad}")
        for line in (DEST / "MANIFEST-SHA256.txt").read_text(encoding="utf-8").splitlines():
            digest, rel = line.split("  ", 1)
            if hashlib.sha256(zf.read(rel)).hexdigest() != digest:
                raise RuntimeError(f"ZIP hash mismatch: {rel}")
    zip_sha = sha(ZIP_PATH)
    (ROOT / "outputs/三款千台落地增量-A5-v0.1-2026-10-10.zip.sha256").write_text(
        f"{zip_sha}  {ZIP_PATH.name}\n", encoding="utf-8",
    )
    print(json.dumps({
        "status": "A5_ENGINEERING_HANDOFF_PACKAGE_VERIFIED",
        "directory": str(DEST),
        "zip": str(ZIP_PATH),
        "zip_sha256": zip_sha,
        "file_count": len(entries) + 1,
        "zip_crc": "PASS",
        "manifest_file_sha256": sha(DEST / "MANIFEST-SHA256.txt"),
    }, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()
