#!/usr/bin/env python3
"""Validate complete, numerically grounded advice before an Analit import."""
import argparse
import json
from pathlib import Path
import jsonschema

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('bundle', type=Path)
    parser.add_argument('advice', type=Path)
    parser.add_argument('--receipt', type=Path, required=True)
    args = parser.parse_args()
    bundle, advice = (json.loads(p.read_text()) for p in [args.bundle, args.advice])
    schema = json.loads((Path.home() / '.agents/skills/keywords-performance-control-advice/schemas/advice_output.schema.v1.json').read_text())
    jsonschema.validate(advice, schema)
    assert advice['snapshot_id'] == bundle['snapshot_id']
    keywords = {k['criterion_id']: k for k in bundle['keywords']}
    rows = {r['criterion_id']: r for r in advice['rows']}
    assert len(rows) == len(advice['rows']), 'Duplicate advice criterion IDs'
    assert rows.keys() == keywords.keys(), 'Incomplete or unknown criterion coverage'
    cited = 0
    flags = 0
    for cid, row in rows.items():
        k = keywords[cid]
        if row['needs_attention']:
            flags += 1
            practical = row.get('practical_advice')
            assert practical, ('Missing practical advice', cid)
            assert [o['label'] for o in practical['options']] == ['A', 'B']
            assert sum(o['recommended'] for o in practical['options']) == 1
            assert row['needs_attention_reason'].strip()
            if not k['impressions']:
                assert k.get('serving_diagnostic'), ('Zero delivery diagnostic missing', cid)
        else:
            assert row.get('practical_advice') is None
        for f in row.get('cited_figures', []):
            assert f['metric'] in bundle['known_metrics']
            actual = k.get(f['metric'])
            assert actual is not None, ('Unavailable citation', cid, f['metric'])
            assert not (f['metric'] == 'quality_score' and actual == 0), ('Absent optional score cannot be cited as zero', cid)
            assert abs(f['cited_value'] - actual) < 0.00001, ('Citation mismatch', cid, f['metric'])
            cited += 1
        terms = bundle['search_terms_by_criterion'].get(cid, [])
        for kind in ['promotion_candidate', 'exclusion_candidate']:
            candidate = row.get(kind)
            if candidate:
                assert set(candidate['search_terms']) <= set(terms)
                if kind == 'exclusion_candidate':
                    assert k['impressions'] >= 200 and k['clicks'] >= 10
        if k['impressions'] < 200 or k['clicks'] < 10:
            assert cid in advice['summary']['wait_for_evidence'], ('Thin row absent from wait lane', cid)
    for lane in advice['summary'].values():
        assert set(lane) <= set(rows)
        assert len(lane) == len(set(lane)), 'Duplicate summary memberships'
    partition = [cid for lane in advice['summary'].values() for cid in lane]
    assert len(partition) == len(rows) and set(partition) == set(rows), 'Summary lanes must partition all criteria exactly once'
    for action in advice.get('top_actions', []):
        assert set(action['affected_criteria']) <= set(rows)
    receipt = dict(snapshot_id=advice['snapshot_id'], schema='PASS', unique_complete_rows=len(rows),
                   exact_cited_values=cited, flagged_rows_with_two_options=flags,
                   grounding='PASS', thin_evidence_wait_membership='PASS')
    args.receipt.parent.mkdir(parents=True, exist_ok=True)
    args.receipt.write_text(json.dumps(receipt, indent=2))
    print(json.dumps(receipt))

if __name__ == '__main__':
    main()
