# -*- coding: utf-8 -*-
"""第4回 PDF「確認事項（第4回）」の自己点検。

原稿 (docs/handoff/TeamWorks確認事項_第4回_20260907.md) の文言が
すべて PDF に含まれているか、フォントが日本語フォントで埋め込まれているかを見る。
PDF のパスは第1引数で渡せる。省略時はこのスクリプトと同じディレクトリ。

check_teamworks_qa3_pdf.py（第3回用）と同じ構成。

★must に「ページを跨ぐ語」を入れないこと★
抽出テキストにフッター（D-Watch / DFA Robotics とページ番号）が挟まり、
空白を詰めても一致しません。第3回で bigint auto_increment が実際に引っかかりました。
"""
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_確認事項_第4回_20260907.pdf"))
if not os.path.exists(PDF):
    raise SystemExit("PDF が見つからない: %s\n"
                     "先に make_teamworks_qa4_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 = [
    # 表題・前文
    "確認事項（第4回）", "TeamWorks（DB開発側）", "clean_watch_20260907.sql",
    "作成日:2026-09-07", "DFARobotics",
    "修正版のDDLをありがとうございました", "受領したその日に照合しています",
    "本書は次の3部構成です",
    # サマリ表
    "1.修正版DDLの照合結果", "7件中2件",
    "5件がまだ入っていません", "状況をお知らせください",
    "2.新しくお願いしたいこと", "W-1は集計の食い違いに直結します",
    "3.第3回からの継続", "まだ回答をいただいていないもの",
    # D-3 の引用ブロック
    "第3回でお伺いしたD-3（セキュリティ解除の判定）は当方で解決しました",
    "制御盤の生死報告", "セキュリティ解除の状態",
    "セキュリティ解除はエラーにならず別の値で管理される",
    "security_statuses.status=0の継続から当方で導出します",
    "回答は不要です",
    # 1. 照合結果
    "clean_watch_20260902.sqlとの差分は14行でした",
    "テーブル数は39で変化ありません",
    "反映されていたもの（2件）",
    "customer_contacts.contact_type", "bigintunsigned", "tinyintunsigned",
    "clean_task_reports", "DEFAULTCURRENT_TIMESTAMP", "ONUPDATE",
    "★まだ入っていないもの（5件）★",
    "A-1", "A-2", "A-3b", "B-1", "B-2", "B-3b",
    "error_idを主キーと位置付けて対応", "PRIMARYKEY無しのまま",
    "履歴テーブルのidを", "auto_incrementで採番",
    "AUTO_INCREMENT無し", "50で09-02版と同数",
    "facility_contacts.emailがvarchar(255)のまま",
    "外部キー3本を追加", "3本とも無し",
    "CONSTRAINT総数が48で09-02版と同数",
    "clean_statuses_clean_timetable_id_foreign",
    "robot_task_versions.clean_schedule_id",
    "KEYはrobot_idのみ",
    "security_status_histories.reported_at",
    "timestampNOTNULLのまま",
    "3つの方法", "各CREATETABLEブロックからの項目抽出",
    "追加されるはずの制約名の全文検索",
    "これから対応", "意図的に見送られた",
    "まとまった段階で改めてDDLをいただけますか",
    "急かす意図はありません",
    "いずれも当方の開発を止めていません",
    "状況が分かれば十分です",
    # 2. W-1
    "2.新しくお願いしたいこと（2件）",
    "W-1", "月跨ぎの週を、どちらの月に数えていますか",
    "週次サマリを作成いただくのはTeamWorks様側",
    "毎週日曜6:00", "前週日〜土",
    "両者で「週の帰属」が食い違うと、同じ週が別の月に集計されます",
    "その月の1日を含む週が、その月の第1週",
    "1日でも翌月が混ざれば、その週は翌月の第1週",
    "2026-08-23(日)〜08-29(土)", "8月の週",
    "2026-08-30(日)〜09-05(土)", "9月第1週",
    "2026-09-06(日)〜09-12(土)", "9月第2週",
    "サマリテーブル側も同じルールでしょうか",
    "週の開始日が属する月",
    "当方の画面（9月第1週）と食い違います",
    "どちらに合わせるべきかご意見をいただけますか",
    "当方はどちらでも実装できます",
    "月次・年次は暦月・暦年の日単位で締める",
    # 2. W-2
    "W-2", "robot_error_reports.error_typeに入る値の一覧をご作成いただけますか",
    "実装は止めずに進めます", "未知の値はすべて「その他」に寄せます",
    "一覧をいただければ分類の精度が上がります",
    "清掃開始の60分前・30分前のロボット状態",
    "robots.statusのコード表と突き合わせると",
    "3つが対応先不明",
    "待機中", "0Standby",
    "充電中", "201ChargingLine/202ChargingPile",
    "セキュリティ有効", "security_statuses.status=1から判定",
    "ハンドルアップ", "緊急停止", "オフライン", "該当なし",
    "網羅でなくて構いません",
    "SELECTDISTINCTerror_type",
    "急ぎではありません", "届いた時点で分類ルールに追加します",
    # 3. 継続
    "3.第3回からの継続（2件）",
    "D-1", "D-4",
    "link_schedules.intervals", "VarChar(120)",
    "実際に入っている値の例を1〜2件",
    "D-Secログの通信断判定が実装できません", "最優先でお願いします",
    "PrecheckItem.idの切替対象",
    "型はvarcharのままという理解でよいか",
    "数値型に変わる可能性があるなら", "破壊的変更",
    "DB更新用アカウントの発行",
    "のみUPDATE可",
    # 末尾
    "おわりに",
    "D-1→W-1→1の5件→W-2の順",
    "D-1が無いとD-Secログの通信状態が出せません",
    "実装が進む前に揃えておきたいです",
    "当方の作業を止めていません",
    "引き続きよろしくお願いします",
]

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)
