"""Verify a browser-only UI publication and remove its hash-verified upload archives."""
import hashlib,json,pathlib,re,subprocess,sys,urllib.error,urllib.request
task,shell_hash=sys.argv[1:]
assert re.fullmatch('[a-z0-9-]+',task) and re.fullmatch('[a-f0-9]{64}',shell_hash)
root=pathlib.Path('/var/www/html/ro-th-online').resolve(strict=True)
baseline=json.loads((root/'staging'/f'{task}-baseline.json').read_text(encoding='utf-8-sig'))
record=json.loads((root/'deploy'/task/'release.json').read_text())
owner=json.loads((root/'deploy'/task/'owner-release.json').read_text())
retention=json.loads((root/f'deploy/browser-retention-completed-{task}.json').read_text())
def sha(path):
    with path.open('rb') as stream:return hashlib.file_digest(stream,'sha256').hexdigest()
assert sha(root/'mobile/index.html')==record['indexHash']
assert sha(root/'public/index.html')==owner['indexHash']
config=pathlib.Path('/etc/apache2/sites-enabled/zz-ro-th-download-ssl.conf').resolve(strict=True)
assert sha(config)==record['configHash']
assert 'ProxyPass /bridge/voice-rtc ws://127.0.0.1:8090/bridge/voice-rtc' in config.read_text()
assert json.loads(pathlib.Path('/var/www/html/test-apk/apks/latest.json').read_text())==baseline['apk']
assert sha(pathlib.Path('/var/www/html/test-apk/patches/Maps/latest.json.gz'))==baseline['mapCatalogHash']
assert subprocess.check_output(['systemctl','cat','ro-th-online-gateway'],text=True)==baseline['gatewayUnit']
for name,expected in baseline['gameServicePids'].items():
    assert subprocess.check_output(['pgrep','-x',name],text=True).strip().splitlines()==expected,name+' PIDs changed'
assert subprocess.check_output(['systemctl','is-active','apache2','ro-th-online-gateway','ro-th-online-voice-rtc'],text=True).splitlines()==['active']*3
kept=sorted(path.name for path in (root/'public/Build').glob('mobile-*') if path.is_dir())
assert kept==sorted('mobile-'+value for value in retention['keep']) and retention['verifiedRetained']
pages=[]
for path,status in [('/Mobile/',200),('/Mobile/?installed=1',200),('/browser/',401),('/',404)]:
    try:response=urllib.request.urlopen('https://ro-th.online'+path,timeout=30)
    except urllib.error.HTTPError as error:response=error
    with response:
        assert response.status==status
        if status==200:assert hashlib.sha256(response.read()).hexdigest()==record['indexHash']
    pages.append(dict(path=path,status=status))
candidates={root/'staging'/f'{task}-build.tar.gz':record['archiveHash'],root/'staging'/f'{task}-shell.tar':shell_hash}
removed=[]
for path,expected in candidates.items():
    assert path.is_file() and not path.is_symlink() and path.resolve(strict=True).parent==root/'staging'
    assert sha(path)==expected
    removed.append(dict(path=str(path.relative_to(root)),bytes=path.stat().st_size,sha256=expected))
for path in candidates:path.unlink()
result=dict(release=record['release'],pages=pages,gameServicePidsUnchanged=True,apacheGatewayVoiceActive=True,
    rtcRoutePreserved=True,gatewayUnitUnchanged=True,retained=kept,retired=retention['retired'],
    removedUploadCopies=removed,apkMetadataUnchanged=True,mapCatalogUnchanged=True,ownerAuthenticationUnchanged=owner['authenticationUnchanged'])
(root/'deploy'/task/'health.json').write_text(json.dumps(result,indent=2))
print(json.dumps(result,indent=2))
