"""Fail closed at boot/manual Start after an interrupted maintenance transaction."""
import hashlib
import json
from pathlib import Path
import subprocess
import connection


def check():
    field=Path('/var/lib/contextra-maintenance/field')
    if (field/'apply-pending.json').exists():
        raise RuntimeError('설정 적용 미완료: ct config resume 또는 ct config restore. ct 메뉴/편집은 사용 가능합니다.')
    if (field/'network-pending.json').exists():
        raise RuntimeError('NIC 적용 미완료: ct net status/restore. 콘솔에서 확인하세요.')
    if (field/'pending.json').exists():
        pending=json.loads((field/'pending.json').read_text())
        if (Path(pending['stage'])/'enroll-intent.json').exists():
            raise RuntimeError('새 Web 발급/적용 확인 필요: ct config status/resume. 이전 세션으로 자동 로그인하지 않습니다.')
    if Path('/var/lib/contextra-maintenance/auth/pending.json').exists():
        raise RuntimeError('Authentication transaction pending. Inspect ct auth status/resume before Start')
    state=Path("/workspace/contextra/runtime/state")
    active=json.loads((state/"active.json").read_text())
    inflight=json.loads((state/"inflight.json").read_text())
    if inflight.get("status")!="DONE" or inflight.get("transaction")!=active["transaction"]:
        raise RuntimeError("Maintenance transaction incomplete; do not auto Start")
    compose=connection.active_compose()
    if compose.parent.name!=active["transaction"]:
        raise RuntimeError("Service/active transaction mismatch")
    for path,expected in ((compose,active["compose_sha256"]),(state/"site.json",active["site_sha256"])):
        if hashlib.sha256(path.read_bytes()).hexdigest()!=expected:
            raise RuntimeError("일반 설정 수동 변경 발견: ct emergency로 변경을 수용하세요. 코드/image/디스크 검증은 유지합니다.")
    site=json.loads((state/"site.json").read_text())
    interfaces=json.loads(subprocess.check_output(["ip","-j","-4","address","show"],text=True,timeout=10))
    if site["ai_ip"] not in {a["local"] for d in interfaces for a in d.get("addr_info",[])}:
        raise RuntimeError("앱의 AI 주소가 실제 NIC와 다릅니다. ct net status와 ct config prepare/connect/apply를 확인하세요.")
    source=active.get("offline_source")
    if source:
        from source_prepare import inspect_tree
        if inspect_tree(Path(source["snapshot"]))!=source["files"]:
            raise RuntimeError("Accepted source snapshot changed")
    print("MAINTENANCE_TRANSACTION_VERIFIED")


if __name__=="__main__":
    check()
