r"""Reproduce a selected-cohort identity comparison, not a residence census.

Standard library only; no network or source edits. Default output is a typed CSV.
--summary prints denominators/unknowns; --verify checks an existing CSV byte-for-byte.
\N in a CSV cell means null/unknown, not zero or an empty string.
"""
from pathlib import Path
import argparse,csv,hashlib,io,json

MAP_SHA256='5398d4a390d15f4bf3e7fbb6b5fd067268f17f8ec82238f1711c9bee03500740'
FIELDS=['origin_record_id','origin_entity_id','origin_name','origin_entity_type','origin_community',
        'origin_evidence_label','origin_source_url','origin_source_publisher','origin_source_class',
        'origin_source_published','origin_source_updated','origin_reviewed','relationship',
        'directory_entity_id','directory_name','directory_entity_type','directory_geographic_scope',
        'directory_base_label','base_source_url','base_source_published','base_record_reviewed',
        'base_access_checked','base_evidence_qualification','identity_proof','birthplace_support','annotation_note']
def pinned(path,digest):
    raw=Path(path).read_bytes()
    if hashlib.sha256(raw).hexdigest()!=digest:raise ValueError('Wrong fixed input edition; no silent historical substitution.')
    return json.loads(raw)
def derive(origins,directory,mapping):
    oo={r['recordId']:r for r in origins['records']};dd={r['entity_id']:r for r in directory['records']}
    if len(oo)!=16 or len(dd)!=47:raise ValueError('Unexpected source cohort.')
    if {r['origin_record_id']for r in mapping['rows']}!=set(oo)or len(mapping['rows'])!=16:raise ValueError('Crosswalk must cover exactly the16qualified origin records.')
    view=[];strict=[]
    for m in mapping['rows']:
        o=oo[m['origin_record_id']];d=dd.get(m['directory_entity_id']);relation=m['relationship']
        if relation=='same_entity':
            if not d or o['entityType']!=d['entity_type']:raise ValueError('Same-entity match must preserve entity type.')
            strict.append(d['entity_id'])
        elif relation=='creator_project_relationship':
            if not d or o['entityType']!='Person'or d['entity_type']!='Organization':raise ValueError('Creator/project association must not merge entities.')
        elif relation=='no_corresponding_current_row':
            if d or m['directory_entity_id']is not None:raise ValueError('Unexpected counterpart.')
        else:raise ValueError('Unknown relationship.')
        r={k:m.get(k)for k in FIELDS}
        r.update(origin_entity_id=o['canonicalEntityId'],origin_name=o['name'],origin_entity_type=o['entityType'],
                 origin_community=o['originCommunity'],origin_source_url=o['primarySource']['url'],
                 directory_name=d['display_name']if d else None,directory_entity_type=d['entity_type']if d else None,
                 directory_geographic_scope=d['geographic_scope']if d else None,directory_base_label=d['location_general']if d else None)
        view.append(r)
    if len(strict)!=len(set(strict)):raise ValueError('Duplicate same-entity mapping.')
    summary=dict(origin_records=16,origin_person_records=sum(r['origin_entity_type']=='Person'for r in view),
                 origin_organization_records=sum(r['origin_entity_type']=='Organization'for r in view),directory_records=47,
                 same_entity_matches=len(strict),creator_project_relationships=sum(r['relationship']=='creator_project_relationship'for r in view),
                 origins_without_corresponding_directory_row=sum(r['relationship']=='no_corresponding_current_row'for r in view),
                 directory_without_same_entity_origin=len(dd)-len(strict),
                 birthplace_explicit_in_retained_citation=sum(r['birthplace_support']=='explicit_in_retained_origin_citation'for r in view),
                 person_birthplace_not_established_in_view=sum(r['birthplace_support']=='not_established_in_this_view'for r in view),
                 organization_birthplace_not_applicable=sum(r['birthplace_support']=='not_applicable_to_organization'for r in view),
                 source_publication_date_unknown=sum(r['base_source_published']is None for r in view if r['relationship']=='same_entity'),
                 units='Selected record correspondence and citation support; no fresh current-location headcount')
    if (summary['same_entity_matches'],summary['creator_project_relationships'],summary['origins_without_corresponding_directory_row'])!=(8,1,7):raise ValueError('Unexpected reviewed identity counts.')
    return dict(summary=summary,rows=view,directory_without_same_entity_origin=[d['entity_id']for d in directory['records']if d['entity_id']not in strict])
def csv_text(view):
    out=io.StringIO(newline='');w=csv.writer(out,lineterminator='\n');w.writerow(FIELDS)
    for r in view['rows']:
        w.writerow('\\N'if r[k]is None else ('\\'+str(r[k])if str(r[k]).startswith('\\')else str(r[k]))for k in FIELDS)
    return out.getvalue()
if __name__=='__main__':
    p=argparse.ArgumentParser(description=__doc__);p.add_argument('origins',type=Path);p.add_argument('directory',type=Path);p.add_argument('crosswalk',type=Path);p.add_argument('--summary',action='store_true');p.add_argument('--verify',type=Path);a=p.parse_args()
    m=pinned(a.crosswalk,MAP_SHA256);v=derive(pinned(a.origins,m['source_sha256']['origins']),pinned(a.directory,m['source_sha256']['directory']),m)
    if a.verify:
        if a.verify.read_bytes()!=csv_text(v).encode():raise SystemExit('Comparison differs from the reviewed reproduction.')
        print('PASS: exact reviewed16-row comparison')
    elif a.summary:print(json.dumps(v['summary'],indent=2))
    else:print(csv_text(v),end='')
