#!/usr/bin/env python3
"""只读校验资源提交；不生成占位素材，不修改工程。python3 validate_submission.py --root 新工程目录"""
import argparse,csv,json,struct
from pathlib import Path
p=argparse.ArgumentParser();p.add_argument('--root',type=Path,required=True);p.add_argument('--manifest',type=Path,default=Path(__file__).with_name('resource-manifest.json'));p.add_argument('--report',type=Path,default=Path('resource-check.json'));a=p.parse_args()
rows=json.loads(a.manifest.read_text());keys=set();paths=set();errors=[];missing=[];present=[]
for r in rows:
 key=r['resource_key'];rel=r['repository_path']
 if key in keys or rel in paths:errors.append({'key':key,'error':'duplicate key/path'})
 keys.add(key);paths.add(rel)
 if Path(rel).is_absolute() or '..' in Path(rel).parts:errors.append({'key':key,'error':'unsafe relative path'});continue
 f=a.root/rel
 if not f.is_file():missing.append({'key':key,'path':rel,'owner':r['owner']});continue
 item={'key':key,'path':rel,'bytes':f.stat().st_size}
 if f.stat().st_size==0:errors.append({'key':key,'error':'empty file'})
 if rel.startswith('Assets/') and not Path(str(f)+'.meta').exists():errors.append({'key':key,'error':'Unity meta missing; import first and commit GUID'})
 if f.suffix.lower()=='.png':
  b=f.read_bytes()[:24]
  if b[:8]!=b'\x89PNG\r\n\x1a\n':errors.append({'key':key,'error':'not valid PNG signature'})
  else:item['pixel_size']=list(struct.unpack('>II',b[16:24]))
 present.append(item)
report={'manifest_count':len(rows),'present_count':len(present),'missing_count':len(missing),'errors':errors,'missing':missing,'present':present,'limits':'只检文件存在、重名、空文件、PNG头和Unity meta。透明底、锚点、九宫格、授权、实际资源绑定与双平台运行仍须人工和引擎检查。源稿可合并为同一Figma文件Frame，冻结映射后更新清单，不要制造空fig占位。'}
a.report.write_text(json.dumps(report,ensure_ascii=False,indent=2));print(json.dumps({k:report[k] for k in ['manifest_count','present_count','missing_count']},ensure_ascii=False));raise SystemExit(1 if errors or missing else 0)
