#!/usr/bin/env python3
import json, hashlib, re, sys
from collections import Counter
from pathlib import Path
PROJECT = 'gacmai_20260718_075153'
CONCEPT_SHA = '0ac2600ec1e964494a688426ed3f59e1bd0d46d4f34982756cfb539a29bed7a0'
CAST = {'Võ Thanh Hà','Nguyễn Hữu Duy','Trần Mộc Lan','Lê Quang Vinh','Phạm Ngọc Thư','Đỗ Minh Khang'}
PROHIBITED = ('siêu nhiên','y khoa','dầu khí','radio','băng ghi âm','lời bài hát')

def sha(p): return hashlib.sha256(p.read_bytes()).hexdigest()
def main():
    p=Path(sys.argv[1]); d=json.loads(p.read_text())
    errors=[]
    if d.get('project_id') != PROJECT: errors.append('project_id')
    if d.get('source_concept_sha256') != CONCEPT_SHA: errors.append('concept_binding')
    parts=d.get('parts',[])
    if len(parts)!=12: errors.append(f'parts={len(parts)}')
    beats=[b for part in parts for b in part.get('beats',[])]
    counts=[len(part.get('beats',[])) for part in parts]
    if counts != [12]*12: errors.append(f'beat_counts={counts}')
    ids=[str(b.get('beat_id','')) for b in beats]
    if len(ids)!=144 or len(set(ids))!=144: errors.append('beat_ids')
    target=sum(int(b.get('target_words',0)) for b in beats)
    if not 14000<=target<=15000: errors.append(f'target_words={target}')
    names=set()
    for x in d.get('named_cast',d.get('cast',[])):
        if isinstance(x,dict) and x.get('name'): names.add(x['name'])
        elif isinstance(x,str): names.add(x)
    if names != CAST: errors.append(f'cast={sorted(names)}')
    pov=json.dumps(d.get('pov',{}),ensure_ascii=False)
    if 'Võ Thanh Hà' not in pov or not re.search(r'(chỉ|duy nhất|only)',pov,re.I): errors.append('pov')
    def value(b,key):
        v=b.get(key,'')
        return json.dumps(v,ensure_ascii=False,sort_keys=True) if not isinstance(v,str) else v.strip()
    dup={}
    continuity_keys = ('continuity_in','continuity_out') if any('continuity_in' in b or 'continuity_out' in b for b in beats) else ('causal_result',)
    for key in ('scene_action',*continuity_keys,'consent_privacy'):
        vals=[value(b,key) for b in beats]
        c=Counter(vals); dup[key]={'unique':len(c),'max_repeat':max(c.values(),default=0)}
        if len(vals)!=len(set(vals)): errors.append(f'duplicate:{key}')
    blob=json.dumps(d,ensure_ascii=False).lower()
    for term in PROHIBITED:
        if term in blob and term not in json.dumps(d.get('hard_rules',[]),ensure_ascii=False).lower(): errors.append(f'prohibited:{term}')
    authority={
      'Khang': ('đỗ minh khang' in blob and ('chứng nhận' in blob or 'mở lại' in blob) and ('trình' in blob or 'khuyến nghị' in blob)),
      'Duy': ('nguyễn hữu duy' in blob and 'ký' in blob and ('điều chỉnh' in blob or 'sửa tuyến' in blob)),
      'Lan': ('trần mộc lan' in blob and ('xác nhận' in blob or 'thẩm tra' in blob) and 'đồng thuận' in blob),
      'Council': ('hội đồng' in blob and ('phê duyệt' in blob or 'quyết định' in blob))
    }
    if not all(authority.values()): errors.append(f'authority={authority}')
    out={'status':'passed' if not errors else 'failed','project_id':PROJECT,'outline_path':str(p),'outline_sha256':sha(p),'concept_sha256':CONCEPT_SHA,'parts':len(parts),'beats':len(beats),'target_words':target,'duplicates':dup,'authority':authority,'errors':errors}
    print(json.dumps(out,ensure_ascii=False,indent=2))
    if errors: raise SystemExit(1)
if __name__=='__main__': main()
