"""Explicit semicolon export and exact read-back for id/place/team strings."""
import argparse,csv,json,io
from pathlib import Path
FIELDS=['id','place','team']
def unique(pairs):
    result={}
    for key,value in pairs:
        if key in result:raise ValueError('duplicate JSON key')
        result[key]=value
    return result
def reject_constant(value):raise ValueError('nonstandard JSON constant')
def convert(source,target):
    with Path(source).open('rb') as f:raw=f.read(1000001)
    if len(raw)>1000000:raise ValueError('demo input byte policy exceeded')
    data=json.loads(raw.decode('utf-8'),object_pairs_hook=unique,parse_constant=reject_constant)
    if not isinstance(data,list):raise ValueError('array required')
    records=[]
    for row in data:
        if not isinstance(row,dict) or set(row)!=set(FIELDS):raise ValueError('id/place/team schema required')
        values=[row[k] for k in FIELDS]
        if not all(isinstance(v,str) for v in values):raise ValueError('string fields required')
        for value in values:value.encode('utf-8',errors='strict')
        records.append(values)
    buffer=io.StringIO(newline='')
    writer=csv.writer(buffer,delimiter=';',quotechar='"',doublequote=True,quoting=csv.QUOTE_MINIMAL,lineterminator='\r\n')
    writer.writerow(FIELDS);writer.writerows(records)
    text=buffer.getvalue()
    recovered=list(csv.reader(io.StringIO(text,newline=''),delimiter=';',strict=True))
    if recovered!=[FIELDS]+records:raise ValueError('in-memory roundtrip failed')
    with Path(target).open('x',encoding='utf-8',newline='') as f:f.write(text)
    with Path(target).open(encoding='utf-8',newline='') as f:
        if list(csv.reader(f,delimiter=';',strict=True))!=[FIELDS]+records:raise ValueError('disk read-back failed')
    print(json.dumps({'records':len(records),'columns':len(FIELDS),'exact_roundtrip':True}))
if __name__=='__main__':
    p=argparse.ArgumentParser();p.add_argument('source');p.add_argument('target');a=p.parse_args()
    try:convert(a.source,a.target)
    except (ValueError,OSError,csv.Error) as error:p.exit(1,type(error).__name__+': '+str(error)+'\n')
