#!/usr/bin/env python3
"""Offline, pinned-key observation summary. No payment decision or network requests."""
import argparse
import datetime as dt
import json
import hashlib
import pathlib
import sys
import verify_archive as verifier


def summarize(bundle, headers, endpoint, start, end, as_of):
    if not endpoint or not start or not end:
        raise ValueError('endpoint and explicit completed-day window are required')
    report = verifier.verify(bundle, headers, as_of, endpoint=endpoint, start=start, end=end)
    result = {
        'schema': 'chainverdict.observation-summary.v1',
        'endpoint': endpoint, 'asOf': as_of, 'window': report['window'],
        'status': 'insufficient_observation', 'counts': None,
        'usableDays': report['usableDays'], 'requestedDays': len(report['days']),
        'selfObservedDays': None, 'findings': [], 'reason': None,
        'verifier': {'pinnedKeyId': verifier.PINNED_KEY['kid'], 'sourceSha256': hashlib.sha256(pathlib.Path(verifier.__file__).read_bytes()).hexdigest()},
        'verification': {'issuer': report['issuer'], 'chainStatus': report['chainStatus'],
                         'days': [{k: row[k] for k in ('day', 'usableEvidence', 'reasons')} | ({'collectionNotes': row['collectionNotes']} if 'collectionNotes' in row else {}) for row in report['days']]},
        'notRecorded': ['price_history', 'pay_to_history', 'x401_history', 'within_day_timing', 'paid_delivery'],
        'limitations': report['limitations'] + [
            'Counts describe this observer only, not continuous uptime or provider fault.',
            'A response includes HTTP errors and redirects. It does not mean a useful service response.',
            'No result authorises a payment or predicts the next response.',
            'Endpoint matching is exact, including case and trailing slash; an absent match is not a health result.',
            'Self-observations are excluded from this integration summary; use the raw verifier to inspect them.',
        ],
    }
    if report['issuer']['status'] != 'authenticated' or report['chainStatus'] != 'valid':
        result['status'] = 'refused'
        result['reason'] = 'publisher authentication or commitment chain did not pass'
        return result
    if report['window']['status'] != 'complete_recent' or not report['days'] or not all(r['usableEvidence'] for r in report['days']):
        result['reason'] = 'requested window is incomplete, stale, excluded or otherwise unusable; inspect per-day reasons'
        return result
    rows = [r['endpointObservation'] for r in report['days']]
    result['selfObservedDays'] = sum(r.get('self') == 1 for r in rows)
    if result['selfObservedDays']:
        result['status'] = 'self_observation_excluded'
        result['reason'] = 'requested window includes own-service observations'
        return result
    counts = {k: sum(r[k] for r in rows) for k in ('p', 'a', 'x', 'v')}
    # The current exporter permits x > a, but that is inconsistent with this collector.
    if any(not 0 <= r['v'] <= r['x'] <= r['a'] <= r['p'] for r in rows):
        result['status'] = 'refused'
        result['reason'] = 'daily counts violate valid offers <= HTTP402 responses <= responses <= probes'
        return result
    result['counts'] = {'probes': counts['p'], 'responses': counts['a'],
                        'http402Responses': counts['x'], 'wellFormedOffers': counts['v']}
    result['status'] = 'observations_available'
    if counts['a'] < counts['p']:
        result['findings'].append('unanswered_probes_observed')
    if counts['v'] < counts['p']:
        result['findings'].append('well_formed_offer_not_observed_on_every_probe')
    return result


def main():
    p = argparse.ArgumentParser(description=__doc__)
    p.add_argument('bundle'); p.add_argument('--headers', required=True)
    p.add_argument('--endpoint', required=True)
    p.add_argument('--from', dest='start', required=True); p.add_argument('--to', dest='end', required=True)
    args = p.parse_args()
    try:
        # Use the real UTC date. No production option to replace the key or bypass work checks.
        result = summarize(verifier.load_json(args.bundle), verifier.load_json(args.headers),
                           args.endpoint, args.start, args.end, dt.datetime.now(dt.timezone.utc).date().isoformat())
        print(json.dumps(result, indent=2, sort_keys=True))
        return 0 if result['status'] == 'observations_available' else 2
    except Exception as e:
        print(json.dumps({'schema': 'chainverdict.observation-summary.v1', 'status': 'refused', 'counts': None, 'reason': str(e)}))
        return 1

if __name__ == '__main__':
    sys.exit(main())
