"""Recompute recorded measurements and verify evidence integrity with Python 3 only."""
from datetime import datetime
import hashlib
import json
from pathlib import Path
import re
import statistics

root = Path(__file__).resolve().parent

def read(name):
    return json.loads((root / name).read_text())

def request(response):
    return next(a for a in response['result']['executionMetadata']['auxiliaryMetadata']
                if a['@type'].endswith('.RequestMetadata'))

def delta(end, start):
    return (datetime.fromisoformat(end.replace('Z', '+00:00')) -
            datetime.fromisoformat(start.replace('Z', '+00:00'))).total_seconds()

record = read('record.json')
expected_ids = [f'{phase}-{n}' for phase in ('baseline', 'fixed') for n in range(1, 4)]
assert [r['id'] for r in record['runs']] == expected_ids, 'All six runs must remain in order'
reference = None
for run in record['runs']:
    stem = run['id']
    invocation = read(stem + '-invocation-mcp.json')['data']['invocation']
    process = read(stem + '.run.json')
    actions = read(stem + '.execution.json')
    responses = read(stem + '.worker-responses.json')
    assert len(actions) == len(responses) == 17
    assert invocation['invocationId'] == process['invocationId'] == run['invocationId']
    assert invocation['exitCode'] == process['exitCode'] == run['exitCode'] == 0
    assert invocation['remoteExecutions'] == run['remoteExecutions'] == 17
    assert invocation['remoteCacheHits'] == run['remoteCacheHits'] == 0
    assert invocation['durationSeconds'] == run['bepInvocationSeconds']
    assert process['wallSeconds'] == run['processWallSeconds']
    assert process['startedAt'] == run['startedAt'] and process['finishedAt'] == run['finishedAt']
    for flag in ('--jobs=16', '--nouse_action_cache', '--disk_cache=', '--remote_accept_cached=false'):
        assert flag in process['arguments'], f'{stem}: missing cache/concurrency control {flag}'
    assert all(a['runner'] == 'remote' and a['cacheHit'] is False and a['exitCode'] == 0 for a in actions)
    signatures = {a['targetLabel']: {k: a[k] for k in ('digest', 'commandArgs', 'inputs', 'actualOutputs', 'environmentVariables', 'platform')} for a in actions}
    assert len(signatures) == 17
    if reference is None:
        reference = signatures
    assert signatures == reference, f'{stem}: action/source/platform/output changed'
    expected_targets = {f'//:unit_{n:02}' for n in range(16)} | {'//:verify'}
    assert set(signatures) == expected_targets
    queues, executions = [], []
    for response in responses:
        req = request(response)
        md = response['result']['executionMetadata']
        target = req['targetId']
        assert req['toolInvocationId'] == run['invocationId']
        assert req['actionId'] == signatures[target]['digest']['hash']
        assert response.get('cachedResult', False) is False
        assert response.get('status', {}).get('code', 0) == 0
        assert response['result'].get('exitCode', 0) == 0
        worker_outputs = {v['path']: (v['digest']['hash'], int(v['digest']['sizeBytes'])) for v in response['result']['outputFiles']}
        bazel_outputs = {v['path']: (v['digest']['hash'], int(v['digest']['sizeBytes'])) for v in signatures[target]['actualOutputs']}
        assert worker_outputs == bazel_outputs
        if target.startswith('//:unit_'):
            queue = delta(md['workerStartTimestamp'], md['queuedTimestamp'])
            execution = delta(md['executionCompletedTimestamp'], md['executionStartTimestamp'])
            assert queue >= 0 and execution >= 1
            queues.append(queue)
            executions.append(execution)
        else:
            output = next(iter(worker_outputs.values()))
            assert output == (record['verifiedOutput']['sha256'], record['verifiedOutput']['sizeBytes'])
    assert len(queues) == run['queueSampleCount'] == 16
    assert round(statistics.mean(queues), 6) == run['meanQueueSeconds']
    assert round(statistics.mean(executions), 6) == run['meanExecutionSeconds']
    log = (root / (stem + '.log')).read_text()
    elapsed, critical = re.search(r'Elapsed time: ([\d.]+)s, Critical Path: ([\d.]+)s', log).groups()
    assert float(elapsed) == run['bazelElapsedSeconds']
    assert float(critical) == run['bazelCriticalPathSeconds']
    samples = [json.loads(line) for line in (root / (stem + '-metrics.raw.jsonl')).read_text().splitlines()]
    assert samples and all(len(s['values']) == len(s['timestamps']) for s in samples)
    print(f"{stem}: 17 matching remote uncached actions; mean queue {run['meanQueueSeconds']:.6f}s; Bazel {elapsed}s; process {run['processWallSeconds']:.6f}s")
assert statistics.median(r['meanQueueSeconds'] for r in record['runs'][:3]) == record['medianBeforeQueueSeconds']
assert statistics.median(r['meanQueueSeconds'] for r in record['runs'][3:]) == record['medianAfterQueueSeconds']
assert all(a['meanQueueSeconds'] < b['meanQueueSeconds'] for a in record['runs'][3:] for b in record['runs'][:3])
assert record['runs'][-1]['bazelElapsedSeconds'] > max(r['bazelElapsedSeconds'] for r in record['runs'][:3])
before = (root / 'config/worker.before.jsonnet').read_text()
after = (root / 'config/worker.after.jsonnet').read_text()
assert before.replace('concurrency: 1,', 'concurrency: 4,', 1) == after
checksum_path = root / 'SHA256SUMS'
if not checksum_path.exists():
    raise SystemExit('Missing SHA256SUMS; integrity check cannot complete')
count = 0
for line in checksum_path.read_text().splitlines():
    digest, name = line.split('  ', 1)
    path = (root / name).resolve()
    assert path.is_relative_to(root.resolve()), 'Checksum entry escapes evidence directory'
    assert hashlib.sha256(path.read_bytes()).hexdigest() == digest, f'Checksum failed: {name}'
    count += 1
print(f'PASS: all six runs, 102 action identities/results, exact configuration change, recomputed means, and {count} file checksums verified.')
