#!/usr/bin/env python3
import json,re,sys,hashlib
from pathlib import Path
from collections import Counter,defaultdict

def norm(s):
 s=s.lower();s=re.sub(r'\b\d+(?:\.\d+)*\b','<n>',s);s=re.sub(r'[^\wÀ-ỹĐđ<> ]+',' ',s);return re.sub(r'\s+',' ',s).strip()
def ngrams(s,n=7):
 w=norm(s).split();return [' '.join(w[i:i+n]) for i in range(max(0,len(w)-n+1))]
def main():
 p=Path(sys.argv[1]);d=json.loads(p.read_text());beats=[b for x in d['parts'] for b in x['beats']];err=[];report={}
 for field in ('scene_action','causal_result'):
  vals=[str(b.get(field,'')) for b in beats];starts=Counter(' '.join(norm(v).split()[:6]) for v in vals);grams=Counter(g for v in vals for g in set(ngrams(v)))
  repeated_starts=[(k,v) for k,v in starts.items() if k and v>=5];repeated_grams=[(k,v) for k,v in grams.items() if v>=8]
  report[field]={'repeated_six_word_starts':sorted(repeated_starts,key=lambda x:-x[1])[:20],'repeated_seven_grams':sorted(repeated_grams,key=lambda x:-x[1])[:30]}
  if repeated_starts:err.append(f'{field}:repeated_sentence_frame')
  if repeated_grams:err.append(f'{field}:repeated_phrase_frame')
 consent=[]
 for b in beats:
  c=b.get('consent_privacy',{});s=json.dumps(c,ensure_ascii=False).lower();act=str(b.get('scene_action','')).lower()
  if ('not_applicable' in s or 'không thu, dùng lại, chuyển giao' in s) and any(x in act for x in ('ảnh','biên bản','đồng thuận','làm mờ','tọa độ','mã','dữ liệu','hồ sơ')):consent.append(b.get('beat_id'))
 # Keyword matching over-flags beats that merely mention a record while correctly making no new permission decision.
 # Keep candidates as review evidence; independent full-read audit adjudicates consent semantics.
 report['consent_action_candidates_for_review']=consent
 banned=('chứng minh quyết định đã bảo toàn','chứng minh tuyến đã bảo toàn','đã bảo toàn lối tiếp cận trong thực tế')
 ending=' '.join(str(b.get('scene_action',''))+' '+str(b.get('causal_result','')) for b in beats[-6:]).lower();hits=[x for x in banned if x in ending]
 if hits:err.append('preconstruction_overclaim')
 out={'status':'passed' if not err else 'failed','path':str(p),'sha256':hashlib.sha256(p.read_bytes()).hexdigest(),'beats':len(beats),'report':report,'ending_overclaim_hits':hits,'errors':err};print(json.dumps(out,ensure_ascii=False,indent=2));raise SystemExit(0 if not err else 1)
if __name__=='__main__':main()
