"""Verify the published browser and remove only this task's verified upload copies."""
import hashlib
import json
import os
from pathlib import Path
import re
import subprocess
import sys
import urllib.error
import urllib.request

task, shell_hash, gateway_archive_hash = sys.argv[1:]
assert re.fullmatch('[a-z0-9-]+', task)
assert all(re.fullmatch('[a-f0-9]{64}', h) for h in (shell_hash, gateway_archive_hash))
root = Path('/var/www/html/ro-th-online').resolve(strict=True)
stage = root / 'staging' / task
deploy = root / 'deploy' / task
release = json.loads((deploy / 'release.json').read_text())
owner = json.loads((deploy / 'owner-release.json').read_text())
gateway = json.loads((deploy / 'gateway-release.json').read_text())
retention = json.loads((root / f'deploy/browser-retention-completed-{task}.json').read_text())
assert retention['verifiedRetained'] and len(retention['keep']) == 3
assert retention['keep'][0] == release['dataHash'][:8]

def sha(path):
    with path.open('rb') as stream:
        return hashlib.file_digest(stream, 'sha256').hexdigest()

def check():
    assert sha(root / 'mobile/index.html') == release['indexHash']
    assert sha(root / 'public/index.html') == owner['indexHash']
    assert sha(root / 'gateway/WebGateway') == gateway['newHash']
    pages = []
    for path, status in [('/Mobile/', 200), ('/Mobile/?installed=1', 200), ('/browser/', 401)]:
        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() == release['indexHash']
        pages.append(dict(path=path, status=status))
    services = subprocess.check_output(['systemctl', 'is-active', 'ro-th-online-gateway', 'apache2'], text=True).splitlines()
    assert services == ['active', 'active']
    kept = sorted(p.name for p in (root / 'public/Build').glob('mobile-*') if p.is_dir())
    assert kept == sorted('mobile-' + value for value in retention['keep'])
    return dict(pages=pages, services=services, retained=kept, ownerIndexHash=owner['indexHash'])

check()
candidates = {
    root / 'staging' / (task + '-build.tar.gz'): release['archiveHash'],
    root / 'staging' / (task + '-shell.tar'): shell_hash,
    root / 'staging' / (task + '-gateway.tar.gz'): gateway_archive_hash,
    stage / 'gateway-candidate/WebGateway': gateway['newHash'],
}
for path, expected in candidates.items():
    assert path.is_file() and not path.is_symlink() and path.resolve(strict=True) == path
    assert path.is_relative_to(root / 'staging') and sha(path) == expected
for proc in Path('/proc').iterdir():
    if not proc.name.isdigit() or proc.name == str(os.getpid()):
        continue
    try:
        assert os.readlink(proc / 'exe') not in {str(p) for p in candidates}, 'Candidate executable still running'
        for fd in (proc / 'fd').iterdir():
            try:
                assert os.readlink(fd) not in {str(p) for p in candidates}, 'Upload still in use'
            except FileNotFoundError:
                pass
    except (FileNotFoundError, PermissionError):
        pass
result = dict(release=release['release'], removed=[], finalChecks=None)
journal = deploy / 'post-cleanup.json'
assert not journal.exists()
for path, expected in candidates.items():
    result['removed'].append(dict(path=str(path.relative_to(root)), bytes=path.stat().st_size, sha256=expected))
    path.unlink()
    journal.write_text(json.dumps(result, indent=2))
(stage / 'gateway-candidate').rmdir()
result['finalChecks'] = check()
journal.write_text(json.dumps(result, indent=2))
print(json.dumps(result, indent=2))
