# -*- coding: utf-8 -*-
"""第3回 PDF「確認事項（第3回）」の自己点検。

原稿 (docs/handoff/TeamWorks確認事項_第3回_20260903.md) の文言が
すべて PDF に含まれているか、フォントが日本語フォントで埋め込まれているかを見る。
PDF のパスは第1引数で渡せる。省略時はこのスクリプトと同じディレクトリ。

check_teamworks_qa2_pdf.py（第2回用）と同じ構成。
"""
import os
import re
import sys

from pypdf import PdfReader

PDF = (sys.argv[1] if len(sys.argv) > 1 else
       os.path.join(os.path.dirname(os.path.abspath(__file__)),
                    "DWatch_確認事項_第3回_20260903.pdf"))
if not os.path.exists(PDF):
    raise SystemExit("PDF が見つからない: %s\n"
                     "先に make_teamworks_qa3_pdf.py を実行するか、"
                     "PDF のパスを第1引数で渡すこと。" % PDF)

raw = open(PDF, "rb").read()
reader = PdfReader(PDF)
pages = [p.extract_text() for p in reader.pages]
text = "\n".join(pages)
flat = re.sub(r"\s+", "", text)

print("== 1. ページ数とサイズ ==")
print("ページ数:", len(reader.pages), " サイズ:", len(raw), "bytes",
      "(%.1f KB)" % (len(raw) / 1024))
print("抽出文字数:", len(text))

print("\n== 2. フォント埋め込み ==")
print("/FontFile2 出現回数:", raw.count(b"/FontFile2"))
biz = sorted(set(re.findall(rb"/([A-Z]{6}\+[A-Za-z0-9\-]*BIZ[A-Za-z0-9\-]*)", raw)))
print("BIZUDGothic を含むフォント名:", biz)
if not biz:
    print("  ★NG★ BIZ UDGothic が埋め込まれていない")
# 中国語向けフォントが混ざっていないこと（CLAUDE.md §0-3）
CN = [b"SimSun", b"SimHei", b"MicrosoftYaHei", b"MSYaHei",
      b"NotoSansSC", b"NotoSerifSC", b"SourceHanSansSC", b"SourceHanSerifSC"]
hit = [n.decode() for n in CN if n in raw]
print("中国語向けフォント:", hit if hit else "混入なし")
if hit:
    print("  ★NG★ 中国語向けフォントが混ざっている")

print("\n== 3. 原稿の全項目が含まれるか ==")
must = [
    # 表題・前文
    "確認事項（第3回）", "TeamWorks（DB開発側）", "作成日:2026-09-03",
    "DFARobotics", "clean_watch_20260902.sql",
    "ご回答をありがとうございました",
    "Q1・Q2で止まっていたD-Security画面と清掃詳細ログの設計が進められます",
    "本書は次の3部構成です",
    # サマリ表
    "1.ご質問への回答", "第2回でいただいた逆質問へのお答え",
    "2.当方で変更するもの", "回答不要", "認識に相違があればご指摘ください",
    "3.追加でお伺いしたいこと", "D-1・D-2が解決しないと画面の中身が埋まりません",
    # 1-1
    "1-1.「備考ってありましたでしょうか?（見落とし?）」について",
    "DB側の項目ではありません。こちら（ビューアー）側で持つべきものでした",
    "セキュリティ復帰失敗", "6時間以上通信なし",
    "アラートは生死報告がないの1種類だけ、詳細文は無い",
    "検知側が出す情報ではなく、運用担当が手で書き留めるメモ",
    "ビューアー側に入力欄を作り、当方の独自ストアに保存します",
    "DB側の対応は不要です",
    "点検記録や運用設定と同じ扱いで、メインDBには書き込みません",
    "control_error_histories.comment",
    "アラート1件ごとに運用担当が対応時に書き込む欄",
    "更新可4カラムの1つ",
    "デバイスごとの備考とは別物",
    # 1-2
    "1-2.「切り替えられる形にした場合のデメリットは?」について",
    "恒久的なコストはほぼありません",
    "切り替える瞬間に2つ、避けられない影響があります",
    "それ以前に画面が持っていたIDが全部無効になります",
    "古いIDで更新をかけて404になります",
    "運用が動いていない時間帯に切り替えていただく",
    "切替をまたぐと、同じレコードが別のIDで記録され、ログの追跡が切れます",
    "切り替えた日時を当方の記録に残しておけば読み替えられる",
    "コードに分岐が残る問題は、作り方で消せます",
    "IDをどちらにするかの決定を1つの関数に閉じ込め",
    "分岐は1箇所だけで済み、テストもその関数に2パターン書けば足ります",
    "切替が現実的に不可能になります",
    "idとerror_idのどちらを使うか",
    "型は両方ともvarcharのまま",
    "bigintauto_increment",
    "破壊的変更",
    # 2. 変更するもの
    "2.当方で変更するもの（回答不要）",
    "2-1", "2-2", "2-3", "2-4",
    "D-Secログの「通信状態」を3状態（正常/通信断/異常）から2状態（正常/異常）に変更",
    "controls.statusが0/1の2値で",
    "通信断と異常は同じもの",
    "D-Secアラートの「種別」列を落とす",
    "制御盤で発生するアラートは「生死報告がない」の1種類だけ",
    "アラートの「詳細」列も落とす",
    "種別が1つしかないため詳細文が存在しない",
    "control_reports.reported_atからの経過時間で行い",
    "link_schedules.intervalsから取る",
    # 3. D-1
    "3.追加でお伺いしたいこと（4件）",
    "D-1", "link_schedules.intervalsの書式",
    "VarChar(120)", "時間帯別の設定（単位:秒）", "書式が分かりません",
    "実際に入っている値の例を1〜2件いただけますか",
    "0-6:600,6-22:120,22-24:600",
    "JSONなのか、区切り文字は何か",
    "これが分からないと通信断の判定が実装できません",
    # 3. D-2
    "D-2", "robot_error_reports.error_typeに実際に入る値",
    "清掃開始の60分前・30分前のロボット状態",
    "robots.statusのコード表と突き合わせると",
    "3つが対応先不明",
    "待機中", "0Standby",
    "充電中", "201ChargingLine/202ChargingPile",
    "セキュリティ有効", "security_statuses.status=1から判定",
    "ハンドルアップ", "緊急停止", "オフライン", "該当なし",
    "PUDUCloud由来で列挙が未定義",
    "実際に入っている値をご存じの範囲で列挙いただけますか",
    "分類ルールはこちらで作り、未知の値は「その他」に寄せます",
    # 3. D-3
    "D-3", "「セキュリティ解除されたまま」の判定",
    "制御盤のアラートは生死報告がないだけ",
    "セキュリティが解除されたまま戻っていない",
    "security_statuses.status=0（セキュリティ無効）が続いている状態から",
    "当方で導出してよいでしょうか",
    "制御盤側でこれを検知してどこかに記録している、ということはありませんか",
    # 3. D-4
    "D-4", "PrecheckItem.idの型",
    "型はvarcharのままという理解でよいですか",
    # 末尾
    "D-Secログの通信断判定と清掃詳細ログの状態表示が完成します",
    "画面とAPIの骨格は作れますので、作業は止まりません",
    "C（修正版DDL）は本日中とのこと、ありがとうございます",
    "prismadbpullで機械的に取り込み、差分をご報告します",
]

miss = [m for m in must if re.sub(r"\s+", "", m) not in flat]
print("検査項目:", len(must), " 欠落:", len(miss))
for m in miss:
    print("  ★欠落★", m)

print("\n== 4. 判定 ==")
ok = (not miss) and bool(biz) and (not hit)
print("結果:", "OK" if ok else "NG")
sys.exit(0 if ok else 1)
