"""Illustrative all-or-nothing price-update preview; does not write a catalogue."""
import csv,io,json,re
from collections import Counter
from decimal import Decimal
RAW='''product_code,description,price_gbp
00124,"Filter, fine",12.50
00420,Seal,
00124,"Filter, fine",13.00
00555,Brush,9.99
00660,Cloth,21.00
'''
existing={'00124':Decimal('11.00'),'00420':Decimal('3.00'),'00660':Decimal('19.99')}
rows=list(csv.DictReader(io.StringIO(RAW,newline='')))
counts=Counter(r['product_code'] for r in rows)
preview=[]
for n,r in enumerate(rows,2):
 code=r['product_code'];price=r['price_gbp'];reason=None
 if counts[code]>1:reason='duplicate product code: no row wins'
 elif not re.fullmatch(r'[0-9]+\.[0-9]{2}',price):reason='expected explicit GBP amount with two decimals'
 before=existing.get(code)
 if reason:action='reject';proposed=None
 else:
  amount=Decimal(price);proposed=f'{amount:.2f}';action='add' if before is None else 'unchanged' if before==amount else 'update'
 preview.append({'line':n,'code':code,'description':r['description'],'before':None if before is None else f'{before:.2f}','proposed':proposed,'action':action,'reason':reason})
assert rows[0]['product_code']=='00124' and rows[0]['description']=='Filter, fine'
assert [r['action'] for r in preview]==['reject','reject','reject','add','update']
report={'records':preview,'batch':'blocked: all-or-nothing policy','proposedValidChanges':2,'writesPerformed':0}
if __name__=='__main__':print(json.dumps(report,indent=2))
