#!/usr/bin/env python3
"""Reproduce descriptive comparability checks for32fixed records. No network or financial arithmetic."""
import argparse,hashlib,json
from pathlib import Path
from collections import Counter
PINS={'creator-earnings-compensation-2026.json':'d4d7771bf47ac2166a6ae6998e9b0c4a636080e026fb2da0409acc5973a3dd73','creator-earnings-source-context-2026-10-30.json':'ca7a001546207d85b49e5f7077fc85d270abbd1865a6d833451b82e455ac51f7','creator-earnings-citation-notes-2026-10-30-v1.json':'c4085e42c6889da13eefa5171f607b5ea78dc3246c62b52eb4ac9c788ea3e2e6'}
MODES=['self_reported','actual','listed','official'];BASES=['unknown','gross payment','gross listed price','net platform revenue']
PAIR_FIELDS=['source_url','publisher','source_name','platform','currency','unit','time_basis','mean_or_median','data_period_start','data_period_end','geography','population_description','evidence_class','compensation_type','measurement_basis','sample_size','actual_or_modeled','transactional','gross_or_net'];MISSING_FIELDS=['creator_tier','follower_min','follower_max','content_format']
def load(folder):
 result={}
 for name,digest in PINS.items():
  raw=(Path(folder)/name).read_bytes()
  if hashlib.sha256(raw).hexdigest()!=digest:raise ValueError('Wrong fixed source edition: '+name)
  result[name]=json.loads(raw)
 return result

def derive(inputs):
 rows=inputs['creator-earnings-compensation-2026.json']['records'];assert len(rows)==32 and len({r['record_id']for r in rows})==32
 assert {r['actual_or_modeled']for r in rows}==set(MODES);assert {r['gross_or_net']for r in rows}==set(BASES)
 matrix=[{'mode':mode,'count':sum(r['actual_or_modeled']==mode for r in rows),'cells':[{'basis':basis,'count':sum(r['actual_or_modeled']==mode and r['gross_or_net']==basis for r in rows),'record_ids':[r['record_id']for r in rows if r['actual_or_modeled']==mode and r['gross_or_net']==basis]}for basis in BASES]}for mode in MODES]
 asks={r['platform']:r for r in rows if r['record_id'].startswith('collabstr-ask-')};payouts={r['platform']:r for r in rows if r['record_id'].startswith('collabstr-payout-')};assert set(asks)==set(payouts) and len(asks)==7
 pairs=[]
 for platform,a in asks.items():
  b=payouts[platform];same=[k for k in PAIR_FIELDS if a[k]is not None and b[k]is not None and a[k]==b[k]];different=[k for k in PAIR_FIELDS if a[k]!=b[k]];unknown=[k for k in MISSING_FIELDS if a[k]is None or b[k]is None]
  pairs.append({'platform':platform,'listed_record_id':a['record_id'],'payout_record_id':b['record_id'],'same_nonnull_fields':same,'different_fields':different,'unknown_metadata_fields':unknown,'matched_transactions_established':False})
 return {'version':'1.0.0','source_sha256':PINS,'records':32,'matrix':matrix,'basis_totals':dict(Counter(r['gross_or_net']for r in rows)),'explicit_creator_net_profit_basis_records':sum(r['gross_or_net']in['creator net profit','net profit','creator net income']for r in rows),'modeled_records_in_frozen_library':sum(r['actual_or_modeled']=='modeled'for r in rows),'missing_metadata_counts':{k:sum(r[k]is None for r in rows)for k in MISSING_FIELDS},'listed_payout_pairs':pairs,'interpretation_limits':['Counts are observations in a selected library, not people, payments or independent samples.','Shared metadata does not establish matched engagements; the source context identifies separate listed/completed populations.','Net platform revenue is a formula denominator, not after-expense creator profit.','Null income periods and survey collection windows do not support a universal monthly take-home estimate.','No financial values are added, averaged, annualized or differenced by this helper.']}
if __name__=='__main__':
 p=argparse.ArgumentParser(description=__doc__);p.add_argument('--data-dir',required=True);p.add_argument('--output');a=p.parse_args();text=json.dumps(derive(load(a.data_dir)),indent=2,ensure_ascii=False)+'\n'
 if a.output:Path(a.output).write_text(text)
 else:print(text,end='')
