"""Export a declared string matrix with an explicit header, after validation.
python matrix-to-csv.py input.json new-output.csv
"""
import csv,json,sys
from pathlib import Path
def unique(pairs):
    result={}
    for k,v in pairs:
        if k in result:raise ValueError('duplicate JSON key: '+repr(k))
        result[k]=v
    return result
def constant(v):raise ValueError('nonstandard JSON constant: '+v)
def main():
    raw=Path(sys.argv[1]).read_bytes()
    if len(raw)>2000000:raise ValueError('recipe input cap: 2000000 bytes')
    data=json.loads(raw.decode('utf-8'),object_pairs_hook=unique,parse_constant=constant)
    if not isinstance(data,dict) or set(data)!={'columns','rows'}:raise ValueError('expected columns and rows only')
    columns,rows=data['columns'],data['rows']
    if not isinstance(columns,list) or not columns or not all(isinstance(c,str) and c for c in columns):raise ValueError('nonempty string column names required')
    if len(set(columns))!=len(columns):raise ValueError('duplicate column name')
    if not isinstance(rows,list):raise ValueError('rows must be an array')
    for i,row in enumerate(rows,1):
        if not isinstance(row,list):raise ValueError('row '+str(i)+' must be an array')
        if len(row)!=len(columns):raise ValueError('row '+str(i)+': expected '+str(len(columns))+' cells, got '+str(len(row)))
        if not all(isinstance(cell,str) for cell in row):raise ValueError('row '+str(i)+': string cells required')
    with Path(sys.argv[2]).open('x',encoding='utf-8',newline='') as f:
        writer=csv.writer(f);writer.writerow(columns);writer.writerows(rows)
if __name__=='__main__':main()
