"""
Independent verifier. Re-reads CDRs straight from SQLite and classifies each call
with a ROW-WISE implementation (deliberately different from analyze.py's vectorized
path), then compares headline numbers to analyze.py's metrics_<year>.json.

Usage:  python3 verify.py [YEAR]     (default 2025)

Any divergence means one of the two implementations has a bug.
"""
import sqlite3, json, sys
import config
from mapping import load_maps, load_live_departments

year = sys.argv[1] if len(sys.argv) > 1 else "2025"
queue_map, direct_map, meta = load_maps()
live_map, live_queues, _live_names = load_live_departments()
PHONE = config.PHONE_RE
HELP = set(config.REPORTING_DIVISIONS)
_CLE_CODES = set(config.REGIONS["cleveland"]["area_codes"])

def classify(row):
    tu = (row.get("call-through-user") or "").strip()
    mu = (row.get("call-term-user") or "").strip()
    if tu == config.MAIN_AA_EXTENSION:
        return None, None, True
    if tu in queue_map:  return queue_map[tu], "queue", False
    if tu in direct_map: return direct_map[tu], "direct", False
    if mu in queue_map:  return queue_map[mu], "queue", False
    if mu in direct_map: return direct_map[mu], "direct", False
    if tu in live_map:   return live_map[tu], ("queue" if tu in live_queues else "direct"), False
    if mu in live_map:   return live_map[mu], ("queue" if mu in live_queues else "direct"), False
    for f in ("call-through-department","call-term-department","call-orig-department"):
        d = config.normalize_dept(row.get(f) or "")
        if d in config.DEPT_CROSSWALK:
            return config.DEPT_CROSSWALK[d], "department", False
    return None, None, False

ans=miss=out=0; talk=0.0; talk_in=0.0; talk_out=0.0; vm=0; q=0; d=0
callers=set(); reached=set()
cle_in=cle_ans=0; cle_callers=set(); vm_total=0

conn = sqlite3.connect(config.DB_PATH)
conn.row_factory = sqlite3.Row
cur = conn.execute(
    'SELECT * FROM cdrs WHERE "call-start-datetime" >= ? AND "call-start-datetime" <= ?',
    (f"{year}-01-01", f"{year}-12-31T23:59:59-05:00"))
for r in cur:
    row = dict(r)
    direction = (row.get("call-direction") or "").strip()
    to_uri = (row.get("call-term-to-uri") or "").lower()
    m_uri = (row.get("call-term-match-uri") or "").lower()
    is_vm = ("vmail" in to_uri) or ("record-vmail" in m_uri)
    if is_vm: vm_total += 1
    mm = PHONE.search(row.get("call-orig-from-uri") or "")
    num = mm.group(1) if mm else ""
    ac = num[:3] if num else ""
    div, route, is_ivr = classify(row)
    # Scope A geo: all real inbound EXCEPT the IVR-998 double-count leg
    if direction in ("1","2") and ac and not is_ivr:
        if ac in _CLE_CODES:
            cle_in += 1
            if num: cle_callers.add(num)
            if direction == "1": cle_ans += 1
    if div in HELP and direction in ("0","1","2"):
        t = float(row.get("call-talking-duration-seconds") or 0)
        talk += t
        if direction == "0":
            out += 1; talk_out += t
        else:
            # inbound-scoped metrics: voicemail + routing counted on attempts only
            talk_in += t
            if is_vm: vm += 1
            if route == "queue": q += 1
            elif route == "direct": d += 1
            if direction == "1":
                ans += 1
                if num: callers.add(num); reached.add(num)
            else:
                miss += 1
                if num: callers.add(num)
conn.close()

actual = {
 "inbound_answered":ans,"inbound_missed":miss,"outbound":out,
 "talk_hours":round(talk/3600,1),
 "talk_hours_in":round(talk_in/3600,1),"talk_hours_out":round(talk_out/3600,1),
 "unique_callers":len(callers),
 "reach_rate":round(100*len(reached)/len(callers),1) if callers else 0,
 "voicemail_count":vm,"queue_count":q,"direct_count":d,
 "cle_inbound":cle_in,"cle_answered":cle_ans,"cle_unique":len(cle_callers),
}

mfile = f"output/metrics_{year}.json"
M = json.load(open(mfile)); exp = M["summary"]; ecle = M["regions"]["cleveland"]["summary"]
expected = {
 "inbound_answered":exp["inbound_answered"],"inbound_missed":exp["inbound_missed"],
 "outbound":exp["outbound"],"talk_hours":exp["talk_hours"],
 "talk_hours_in":exp["talk_hours_inbound"],"talk_hours_out":exp["talk_hours_outbound"],
 "unique_callers":exp["unique_callers"],"reach_rate":exp["reach_rate"],
 "voicemail_count":exp["voicemail_count"],"queue_count":exp["queue_count"],
 "direct_count":exp["direct_count"],
 "cle_inbound":ecle["inbound_attempts"],"cle_answered":ecle["inbound_answered"],
 "cle_unique":ecle["unique_callers"],
}

print(f"=== independent verify of {mfile} ===")
print(f"{'metric':<22}{'independent':>14}{'analyze.py':>14}  match")
ok = True
for k in expected:
    a, e = actual[k], expected[k]; m = (a == e); ok = ok and m
    print(f"{k:<22}{str(a):>14}{str(e):>14}  {'OK' if m else 'MISMATCH <<<'}")
print(f"\n(raw voicemail across all directions, independent: {vm_total:,})")
print("RESULT:", "ALL HEADLINE NUMBERS MATCH" if ok else "DISCREPANCY FOUND")
sys.exit(0 if ok else 1)
