"""Recompute EBPMan coverage metrics from the supplied public metadata snapshot.
Usage: python3 analyze.py [audit-folder] -- no network or third-party packages.
"""
import json,re,sys,unicodedata,collections,datetime
from pathlib import Path
ROOT=Path(sys.argv[1]) if len(sys.argv)>1 else Path(__file__).resolve().parent
load=lambda name:json.loads((ROOT/name).read_text())
rows=load('catalog.json');aliases=load('brand-aliases.json');overrides=load('brand-overrides.json')
patterns={b:re.compile(r'(?<!\w)(?:'+'|'.join(re.escape(a) for a in aa)+r')(?!\w)',re.I) for b,aa in aliases.items()}
def normalized(t):return re.sub(r'[^a-z0-9]+','',unicodedata.normalize('NFKD',t).encode('ascii','ignore').decode().lower())
seen={};result=[]
for v in reversed(rows):
 v=dict(v);title=v['title'];brands={b for b,p in patterns.items() if p.search(title)};o=overrides.get(v['id'],{});brands.update(o.get('add',[]));brands.difference_update(o.get('remove',[]))
 if 'eufy' in brands and re.search(r'\bE1\b',title,re.I):brands.discard('eufy');brands.add('eufyMake')
 v['brands']=sorted(brands);v['evidenceBasis']='title_or_named_product_alias'+('+reviewed_description' if o.get('add') else '')
 if o:v['manualEvidence']=o
 why=[]
 if v['tab']!='videos':why.append('shorts_tab' if v['tab']=='shorts' else 'streams_tab')
 if re.search(r'#shorts?\b',title,re.I):why.append('short_tag')
 key=normalized(title)
 if not why:
  if key in seen:why.append('duplicate_normalized_title:'+seen[key])
  else:seen[key]=v['id']
 v['exclusions']=why;v['included']=not why
 d=v.get('description','');flags=[]
 if re.search(r'\bnot\s+(?:a\s+)?sponsored\b',d,re.I):flags.append('explicit_not_sponsored')
 if re.search(r'(?:I|we) (?:was|were) provided (?:this|the|a) product|(?:provided|sent) (?:me|us|to me|to us) (?:with )?(?:this|the|a|an) (?:unit|product)|xTool provided me',d,re.I):flags.append('product_provided_disclosure')
 if re.search(r'\bsponsored review\b',title,re.I) or re.search(r'\bthis video\s+(?:is|was)\s+sponsored\b|\bpaid partnership with\b|#sponsored\b|#ad\b',d,re.I):flags.append('explicit_sponsorship_disclosure')
 if '#samsungpartner' in (title+'\n'+d).lower():flags.append('brand_partner_tag_terms_unknown')
 if v.get('paidPromotion'):flags.append('youtube_paid_promotion_flag')
 v['disclosureFlags']=flags;result.append(v)
result.reverse();included=[v for v in result if v['included']];featured=[v for v in included if v['brands']]
counts=collections.Counter(b for v in featured for b in v['brands']);repeat=sum(n>=2 for n in counts.values())
start='2025-09-01';end='2026-09-01'
annual=[v for v in included if start<=v.get('published','')[:10]<end]
annual_counts=collections.Counter(b for v in annual for b in v['brands'])
brandrows=[{'brand':b,'videoCount':n,'annualVideoCount':annual_counts[b],'videoIds':[v['id'] for v in featured if b in v['brands']]} for b,n in counts.most_common()]
summary={'auditDate':'2026-09-24','channelId':'UCYO_YUHK7ZROCqJMtSOuOHQ','listedUniqueVideos':len(rows),'tabs':dict(collections.Counter(v['tab'] for v in rows)), 'titlesAudited':len(rows),'exactPublicationDates':sum(bool(v.get('published')) for v in rows),'descriptionsRetrieved':sum('description'in v for v in rows),'includedStandardVideos':len(included),'excludedStandardVideoTitles':[{'id':v['id'],'title':v['title'],'reasons':v['exclusions']} for v in result if v['tab']=='videos' and v['exclusions']],'identifiedBrandVideos':len(featured),'distinctIdentifiedBrands':len(counts),'repeatBrands':repeat,'repeatBrandCoveragePercent':round(repeat/len(counts)*100,1),'annualPeriodStartInclusive':start,'annualPeriodEndExclusive':end,'annualStandardVideos':len(annual),'annualIdentifiedBrandVideos':sum(bool(v['brands']) for v in annual),'annualDistinctIdentifiedBrands':len(annual_counts),'brandCoverageEvidencedSince':'2011-04-08','brandCoverageEvidenceVideo':'ZxqmGS0LCOM','confirmedSponsorEvidenceVideos':[v['id'] for v in result if 'explicit_sponsorship_disclosure' in v['disclosureFlags']],'disclosureCountsOverFetchedDescriptions':dict(collections.Counter(f for v in result if 'description'in v for f in v['disclosureFlags']))}
for name,data in [('summary.json',summary),('classified-catalog.json',result),('brand-counts.json',brandrows)]: (ROOT/name).write_text(json.dumps(data,ensure_ascii=False,indent=2)+'\n')
print(json.dumps(summary,indent=2))
