import sys, json, tempfile, os, time
NET=[]
def hook(ev,args):
    if ev in ("socket.connect","socket.getaddrinfo","socket.sendto"): NET.append((ev,str(args)[:80]))
sys.addaudithook(hook)
from tensemem import Memory
from tensemem.providers.llm.fake import FakeExtractor
from tensemem.core.models import ExtractionResult, ExtractedOp, OpKind
R={}
def mem(d, llm=None):
    m=Memory(os.path.join(d,"t.db"), llm=llm or FakeExtractor()); m.register_predicate("lives_in"); return m
def fv(fs): return [(f.subject,f.predicate,f.object,str(f.status)) for f in fs.facts]
dirs=[]
# C1
d=tempfile.mkdtemp(); dirs.append(d); m=mem(d)
for t in ["I live in Delhi","I moved to Bangalore","Maybe I will move to Mumbai","I moved to Pune"]: m.add("u1",t,wait=True)
m.add("u2","I live in Paris",wait=True)
s1=m.state("u1"); h1=m.history("u1","lives_in"); s2=m.state("u2")
st={f.object:str(f.status) for f in h1.facts}
R["C1"]={"state_u1":s1.values,"history_u1":fv(h1),"state_u2":s2.values,
 "checks":[s1.values.get("lives_in")=="Pune", "ACTIVE" in st.get("Pune",""), "SUPERSEDED" in st.get("Bangalore","") and "SUPERSEDED" in st.get("Delhi",""),
           "Mumbai" not in st, s2.values.get("lives_in")=="Paris" and "Paris" not in st]}
# C3a
ctx=m.context("u1","where do I live?")
R["C3a_context_text"]=ctx.text
m.add("u3",ctx.text,wait=True); s3=m.state("u3"); R["C3a_u3_facts"]=fv(s3); R["C3a_pass"]=len(s3.facts)==0
m.close()
# C3b lying extractor
d=tempfile.mkdtemp(); dirs.append(d)
lie=ExtractionResult(ops=(ExtractedOp(subject="user",predicate="lives_in",object="Tokyo",op=OpKind.SET,evidence="I live in Tokyo"),))
m=mem(d, FakeExtractor({"Hello there":lie})); m.add("u6","Hello there",wait=True)
s6=m.state("u6"); R["C3b_u6_facts"]=fv(s6); R["C3b_pass"]=not any(f.object=="Tokyo" for f in s6.facts if "ACTIVE" in str(f.status))
m.close()
# C4
d=tempfile.mkdtemp(); dirs.append(d); m=mem(d)
m.add("u4","I live in Delhi",wait=True); m.add("u4","I moved to Bangalore",wait=True)
b=[f for f in m.state("u4").facts if f.object=="Bangalore"][0]
m.correct(b.id); a=m.state("u4").values; R["C4_after_correct"]=a; m.close()
m=mem(d); v=m.rebuild("u4",wait=True); a2=m.state("u4").values; h4=fv(m.history("u4","lives_in"))
R["C4_after_rebuild"]=a2; R["C4_history"]=h4
R["C4_checks"]=[a.get("lives_in")=="Delhi", a2.get("lives_in")=="Delhi" and not any(x[2]=="Bangalore" and "ACTIVE" in x[3] for x in h4)]
m.close()
# C2 freshness
d=tempfile.mkdtemp(); dirs.append(d); m=mem(d); lies=0; ok=0; rows=[]
for i in range(20):
    city=f"City{chr(65+i)}x"
    r=m.add("u5",f"I moved to {city}")
    c0=m.context("u5","where do I live?",min_seq=r.seq,wait=0); s0=m.state("u5")
    if c0.freshness.is_current and city not in c0.text: lies+=1
    if s0.freshness.is_current and s0.values.get("lives_in")!=city: lies+=1
    c1=m.context("u5","where do I live?",min_seq=r.seq,wait=2.0)
    good=c1.freshness.is_current and city in c1.text
    ok+=good
    rows.append({"i":i,"seq":r.seq,"imm_ctx":c0.freshness.model_dump(),"imm_cur":c0.freshness.is_current,"imm_has":city in c0.text,
                 "state_cur":s0.freshness.is_current,"state_val":s0.values.get("lives_in"),"wait_cur":c1.freshness.is_current,"wait_has":city in c1.text})
R["C2"]={"lies":lies,"current_after_wait":ok,"rows":rows}
m.close()
R["net_events"]=NET
R["files"]={d:sorted(os.listdir(d)) for d in dirs}
print(json.dumps(R,indent=1,default=str))
