"""Audit interval-average hourly rates. Python standard library only."""
from pathlib import Path
from datetime import datetime,timedelta,timezone
from collections import defaultdict
import csv,math
root=Path(__file__).resolve().parent
values={};duplicates=[]
with (root/'demand_hourly_raw.csv').open() as f:
 for row in csv.DictReader(f):
  t=datetime.fromisoformat(row['timestamp_utc'])
  q=float(row['demand_m3_h'])
  if t.utcoffset() is None or t.minute or t.second or t.microsecond:
   raise ValueError('Timestamp must be an aligned, timezone-aware hour')
  if not math.isfinite(q) or q<0:raise ValueError('Invalid or negative demand needs investigation')
  t=t.astimezone(timezone.utc)
  if t in values:
   if values[t]!=q:raise ValueError(f'Conflicting duplicate: {t}')
   duplicates.append(t)
   continue  # Identical duplicate in this documented fixture only.
  values[t]=q
first=datetime(2026,1,1,tzinfo=timezone.utc)
expected=[first+timedelta(hours=h) for h in range(56*24)]
if any(t<expected[0] or t>expected[-1] for t in values):
 raise ValueError('Data outside the configured study interval')
missing=[t for t in expected if t not in values]
days=defaultdict(list)
for t in expected:days[t.date()].append(t)
output=[]
for day,hours in sorted(days.items()):
 present=[t for t in hours if t in values]
 complete=len(hours)==24 and len(present)==24
 # Each rate represents one complete hour. No interpolation of missing hours.
 volume_ml=sum(values[t] for t in present)/1000 if complete else ''
 output.append([day,len(present),complete,volume_ml])
with (root/'daily_audit.csv').open('w',newline='') as f:
 w=csv.writer(f);w.writerow(['date','hours_present','complete','volume_ml']);w.writerows(output)
print('Unique hours:',len(values))
print('Identical duplicates:',len(duplicates))
print('Missing hours:',len(missing))
print('Complete days:',sum(row[2] for row in output))
print('Missing timestamps:',[t.isoformat() for t in missing])
