"""Validate evidence completeness; never assess truth or infer causality."""
import csv,sys,json
from collections import defaultdict
from datetime import datetime
from urllib.parse import urlparse

def filled(value):return bool(value.strip()) and not value.strip().startswith('[')
def check(path):
 with open(path,encoding='utf-8-sig',newline='') as f:
  reader=csv.DictReader(f); fields=reader.fieldnames or [];rows=list(reader)
 required=['day','question_id','question','platform','settings','market','language','checked_at','run_status','brand_mentioned','recommended','target_cited','any_citations','answer_capture','source_urls','notes']
 if any(k not in fields for k in required):raise ValueError('Missing required CSV columns')
 summaries=defaultdict(lambda:{'captured':0,'mentioned':0,'recommended':0,'target_cited':0,'any_citations':0})
 incomplete=[];seen=set();captured_total=0;failed_missed=0
 for index,row in enumerate(rows,2):
  issues=[];key=(row['day'],row['question_id'])
  if key in seen:issues.append('duplicate day/question')
  seen.add(key)
  for k in ['day','question_id','question','platform','settings','market','language']:
   if not filled(row[k]):issues.append(k)
  if row['day'] not in [str(x) for x in range(1,8)]:issues.append('day must be 1–7')
  status=row['run_status']
  if status not in ['captured','failed','missed']:issues.append('run_status')
  if status=='captured':
   captured_total+=1
   for k in ['checked_at','answer_capture']:
    if not filled(row[k]):issues.append(k)
   try:
    date=datetime.fromisoformat(row['checked_at'].replace('Z','+00:00'))
    if date.utcoffset() is None:issues.append('timestamp needs timezone')
   except ValueError:issues.append('invalid timestamp')
   for k in ['brand_mentioned','recommended','target_cited','any_citations']:
    if row[k] not in ['yes','no']:issues.append(k)
   if row['recommended']=='yes' and row['brand_mentioned']!='yes':issues.append('recommendation requires mention')
   if row['target_cited']=='yes' and row['any_citations']!='yes':issues.append('target citation requires any citation')
   if row['any_citations']=='yes':
    urls=[u.strip() for u in row['source_urls'].split('|')]
    if not urls or any(urlparse(u).scheme not in ['http','https'] or not urlparse(u).netloc for u in urls):issues.append('source_urls')
  elif status in ['failed','missed']:
   failed_missed+=1
   if not filled(row['notes']):issues.append('explain failed/missed check in notes')
  if issues:incomplete.append({'row':index,'question_id':row['question_id'],'issues':issues})
  elif status=='captured':
   group=(row['question_id'],row['question'],row['platform'],row['settings'],row['market'],row['language'])
   item=summaries[group];item['captured']+=1
   for k in ['brand_mentioned','recommended','target_cited','any_citations']:item[{'brand_mentioned':'mentioned'}.get(k,k)]+=row[k]=='yes'
 return {'records':len(rows),'captured_answers':captured_total,'failed_or_missed':failed_missed,'incomplete_records':len(incomplete),'issues':incomplete,'comparable_series':[{'question_id':k[0],'question':k[1],'platform':k[2],'settings':k[3],'market':k[4],'language':k[5],**v} for k,v in summaries.items()]}
if __name__=='__main__':
 if len(sys.argv)!=2:raise SystemExit('Usage: python3 check-register.py lens-74-seven-day-check.csv')
 try:print(json.dumps(check(sys.argv[1]),ensure_ascii=False,indent=2))
 except (ValueError,OSError) as e:raise SystemExit(str(e))
