#!/usr/bin/env python3
"""Backfill SLICE 4 (LIMIT 92 OFFSET 276) of Ahmed's WhatsApp outreach CRM into jarvis-memory.
Reads MEMORY_API_KEY from ../.env (never printed). POST one fact per lead to /remember.
Run: python3 backfill_s4.py            (real POST)
     DRY_RUN=1 python3 backfill_s4.py  (validate payloads only, no network)
"""
import os, json, time, urllib.request, urllib.error

ENV = "/Users/ahmed/devFolder/Ultron/claude-voice/.env"
BASE = "https://jarvis-production-3e5f.up.railway.app"
ACCT = "966565625560"

def load_key():
    for line in open(ENV, encoding="utf-8"):
        line = line.strip()
        if line.startswith("MEMORY_API_KEY="):
            return line.split("=", 1)[1].strip()
    raise SystemExit("MEMORY_API_KEY not found")

# Campaign phrase used inside the fact text
CAMP = {
    "AIN": "AIN (عين) AI-camera-monitoring",
    "RevalGames": "Reval team-building video-game",
    "RevalAgency": "Reval Agency social-media/content/design",
    "Job": "Ahmed's job-search (prove-myself + CV)",
    "Outreach": "targeted-outreach / lead-gen service",
}
# Campaign entity name saved to the graph
CAMP_ENTITY = {
    "AIN": "AIN",
    "RevalGames": "Reval Games",
    "RevalAgency": "Reval Agency",
    "Job": "Ahmed job outreach",
    "Outreach": "Ahmed outreach service",
}

# Each record: (peer, name, campaign_key, importance, when_iso, arc, stage, nxt)
COLD = "cold pitch sent, no reply"
R = []

def cold(peer, name, camp, date):
    R.append((peer, name, camp, 2, date, f"{date} {COLD}", "cold-sent, no reply", "Follow-up or drop."))

def auto(peer, name, camp, date):
    R.append((peer, name, camp, 2, date, f"{date} cold pitch sent, only a business auto-reply came back", "cold-sent, auto-reply only (no human)", "Re-approach a human contact or drop."))

# ---- AIN cold, no reply ----
for peer, name, date in [
    ("249138335748294","Ali","2026-07-13"),
    ("250160403746969","Abdullah","2026-07-15"),
    ("255825633370356","Aiman","2026-07-15"),
    ("257375999156307","Ziad","2026-07-07"),
    ("262899259936981","Mohamed","2026-07-13"),
    ("263418951012404","Basma","2026-07-07"),
    ("263758287003659","Abdullah","2026-07-13"),
    ("2641589469381","Alok","2026-07-15"),
    ("265828461191339","Mohanad","2026-07-13"),
    ("26822221803621","Khalid","2026-07-15"),
    ("272163521204450","Abdulwahab","2026-07-07"),
    ("272180717838565","Ibrahim","2026-07-07"),
    ("273379064021216","Mishal","2026-07-07"),
    ("275900243439670","Mishari","2026-07-13"),
    ("276488653951223","Hashim","2026-07-13"),
    ("277119896658056","Wael","2026-07-15"),
    ("277562295095357","Feras","2026-07-13"),
    ("280298273140983","Mowaffag","2026-07-13"),
    ("31645470036223","Majed","2026-07-07"),
    ("35424974172210","Ziyad","2026-07-07"),
    ("38452942917716","Nassir","2026-07-13"),
    ("39281854816471","Ahmed","2026-07-13"),
    ("41446484775012","Abdulmajeed","2026-07-15"),
]:
    cold(peer, name, "AIN", date)

# AIN cold, no reply, with company / notes
R.append(("251659397685296","Hisham","AIN",2,"2026-07-15","2026-07-15 cold pitch sent, no reply (possibly the 'Hisham' that Adnan Younes / Sprout said would make contact)","cold-sent, no reply","Follow-up; may tie to the Sprout referral."))
R.append(("252711614304261","Saeed Alali","AIN",2,"2026-07-07","2026-06-29 personalized cold pitch (company Aggcom Holding), then a 2026-07-07 follow-up cold pitch, no reply either time","cold-sent x2, no reply","Follow-up or drop."))
R.append(("268263808303126","Jameel","AIN",2,"2026-07-13","2026-07-13 cold pitch + a 'مناسب' nudge, no reply","cold-sent, no reply","Follow-up or drop."))
R.append(("274783635828962","Bander Hamooh","AIN",2,"2026-06-29","2026-06-29 personalized cold pitch (company Panda Retail Company – Savola Group), no reply","cold-sent, no reply","Follow-up — large retail account, worth a retry."))

# ---- AIN engaged ----
R.append(("248429632553014","Adnan Younes","AIN",3,"2026-06-29","2026-06-29 personalized cold pitch (company Sprout | سبراوت); lead replied that someone named Hisham would reach out","replied — referred to Hisham (Sprout)","Chase the Hisham handoff at Sprout."))
R.append(("250276434976882","Yazan Al-Natour","AIN",3,"2026-06-29","lead (Yazan Al-Natour, from Sprout / سبراوت) messaged 2026-06-29 after failing to reach Ahmed by call, asked for program details; Ahmed gave his personal number (0544067114) and sent the proposal doc; lead thanked and went quiet","replied — proposal doc sent, awaiting","Follow up on the Sprout trial."))
R.append(("265695333994526","Mohammed","AIN",4,"2026-07-13","2026-07-13 cold pitch; lead asked to be sent the proposal, camera specs and prices; Ahmed sent the doc, clarified AIN does NOT sell cameras (runs on existing ones) and asked how many cameras/branches","interested — awaiting camera count for pricing","Get camera count, then quote."))
R.append(("280293927850231","Malik Alahmadi","AIN",3,"2026-06-29","2026-06-29 personalized cold pitch (company Food Unit Company); lead replied warmly, Ahmed explained the partner-trial and proposed a call/meeting","replied warmly — meeting proposed, awaiting","Lock a meeting time."))
R.append(("280800868225163","Waleed Alamoudi","AIN",3,"2026-07-01","2026-06-29 personalized cold pitch (company مجموعة العامودي | Al Amoudi Group); lead replied warmly 06-30 and sent a voice note; Ahmed tried to call 07-01, no answer, asked to reschedule","engaged — call attempted, awaiting reschedule","Retry the call / propose a slot."))
R.append(("34420018905209","Julio","AIN",3,"2026-07-13","2026-07-13 cold pitch; English due-diligence exchange — lead asked company name, website, what happens to the data, whether it's a Gov company, and about MOI approval to access CCTV; Ahmed explained it's a startup, on-site server so nothing leaves the premises, licensing in progress; lead said to circle back once licensed","interested but blocked — wants AIN licensed (MOI) first","Re-contact after licensing lands."))
R.append(("40119390204039","Jawad","AIN",3,"2026-07-13","2026-07-13 cold pitch; lead shared a contact card and said to reach 'brother Ahmed'","replied — referred to another contact (Ahmed)","Reach the referred contact."))
R.append(("274491410243725","Rustic Bakery","AIN",4,"2026-06-29","opener was a voice note so campaign is inferred (AIN, matches the 06-29 batch); 2026-06-29 Ahmed proposed a meeting tomorrow at 11 then agreed 1pm; lead collected team emails (a.lotfy@ / management3@ / supervisor1@ / y.altewejri@rustic-bakery.com) and confirmed","meeting booked (next day 1pm) — emails collected","Run the scheduled demo meeting."))

# ---- Reval Games cold, no reply ----
for peer, name, date in [
    ("255868566274065","Mishal","2026-06-19"),
    ("259630940836062","Roaa","2026-06-19"),
    ("260665910534250","Hatem","2026-06-19"),
    ("270419798024372","Eng","2026-06-17"),
    ("274985331507417","Ahmed","2026-06-17"),
    ("277128486641826","Badr","2026-06-19"),
    ("281462276378867","Ahlam","2026-06-19"),
    ("30747838705852","Fawzia","2026-06-17"),
    ("31349033402575","Mona","2026-06-17"),
    ("34866678730998","Abdulilah","2026-06-17"),
    ("35038410342507","Noushad","2026-06-17"),
    ("36052039368923","Rima","2026-06-19"),
    ("39277643706454","Puja","2026-06-17"),
    ("39569701486812","Shahad","2026-06-19"),
    ("43271913005290","Saad","2026-06-19"),
]:
    cold(peer, name, "RevalGames", date)
R.append(("258939484659944","Lama","RevalGames",2,"2026-06-17","2026-06-17 cold pitch; only a hospital medical-file auto-reply bounced back","cold-sent, auto-reply only (no human)","Wrong-target / drop."))
R.append(("32276779954215","Abdullah","RevalGames",2,"2026-06-17","2026-06-17 cold pitch; lead sent only a blank/empty message","cold-sent, no real reply","Follow-up or drop."))

# ---- Reval Games engaged ----
R.append(("247983006302304","Majed","RevalGames",4,"2026-06-29","2026-06-17 cold pitch; lead said 'send it', Ahmed sent an example (Al Rugaib collab) + World-Cup games portfolio; lead asked to set an appointment to see a presentation; Ahmed asked when suits and re-nudged 2026-06-29 to arrange a meeting","interested — meeting requested by lead, awaiting scheduling","Pin the meeting time."))
R.append(("365139361873","Khalid","RevalGames",4,"2026-06-29","2026-06-19 cold pitch; lead said 06-22 he needs to see it; 06-29 gave email K.Alamri@alhilal.com (Al Hilal club domain); Ahmed promised to send the portfolio the next morning","interested — email collected (Al Hilal), portfolio to send","Send portfolio; follow the Al Hilal lead."))

# ---- Reval Agency cold, no reply ----
for peer, name, date in [
    ("248292713713847",None,"2026-07-03"),
    ("253527708410016",None,"2026-07-03"),
    ("25787134648337",None,"2026-07-03"),
    ("257131756417174",None,"2026-04-07"),
    ("262568648138928",None,"2026-04-07"),
    ("262916490191045",None,"2026-04-16"),
    ("263775970181255",None,"2026-04-16"),
    ("265094575484976","Arkoma team","2026-04-05"),
    ("266864034869346",None,"2026-07-03"),
    ("270471505432748",None,"2026-07-03"),
    ("274568753193195",None,"2026-04-16"),
    ("275247324487824",None,"2026-04-07"),
    ("279473857515593",None,"2026-04-07"),
    ("28114973397219",None,"2026-07-03"),
    ("28802151391326",None,"2026-07-03"),
    ("2985740521553",None,"2026-07-03"),
    ("30009607618660",None,"2026-07-03"),
    ("31250500837468",None,"2026-04-16"),
    ("34725548843263",None,"2026-07-03"),
    ("44900091470037",None,"2026-04-16"),
]:
    cold(peer, name, "RevalAgency", date)

# ---- Reval Agency auto-reply only ----
for peer, name, date in [
    ("252385767256204","Bou Hassan restaurant","2026-04-16"),
    ("268715232854022","Sondos Cheesecake","2026-04-15"),
    ("274341539348595","Wesal Coffee","2026-04-07"),
    ("279722680402082","Al Barari farm (مزرعة البراري)","2026-04-16"),
    ("29258089033842","Brown Branch","2026-07-03"),
    ("40343332507833","Coplant","2026-07-03"),
]:
    auto(peer, name, "RevalAgency", date)

# ---- Reval Agency engaged ----
R.append(("248378109771866",None,"RevalAgency",3,"2026-04-16","2026-04-16 free-design cold offer; lead was polite but declined — already works with a designer, will save the number for later","declined — already has a designer","Keep on a re-touch list."))
R.append(("261894992609361",None,"RevalAgency",3,"2026-04-19","2026-04-07 content pitch + 2026-04-16 free-design offer; lead replied 04-19 asking 'where is the design?' — Ahmed did not follow through in chat","interested — asked for the promised design, unanswered","Deliver the free design sample."))
R.append(("264097706823816",None,"RevalAgency",3,"2026-04-18","2026-04-16 free-design offer; lead agreed ('why not'), Ahmed asked for a product + logo, lead sent product images 04-16/04-18","interested — product images received, free design owed","Produce and send the free design."))
R.append(("32074899689608",None,"RevalAgency",3,"2026-04-16","2026-04-16 free-design offer; lead replied asking which product the design is for","replied — asked which product to design","Reply with the product and deliver."))
R.append(("33514066071597",None,"RevalAgency",3,"2026-04-16","2026-04-16 free-design offer; lead agreed ('no problem'), Ahmed asked him to share a product + logo","interested — awaiting the product to design","Get the product asset, deliver design."))

# ---- Job outreach cold, no reply (CV attached) ----
for peer, name, date in [
    ("256688770805943","Mohammed","2026-07-01"),
    ("260794759520371","Nabeel","2026-07-01"),
    ("27401908146314","Mohammed","2026-07-02"),
    ("29339072634937","Sattam","2026-07-02"),
]:
    R.append((peer, name, "Job", 2, date, f"{date} cold job-outreach as Ahmed Al Rajeh — offered to build a working product for a real problem of theirs, no strings, with CV attached; no reply", "cold-sent (CV), no reply", "Follow-up or drop."))

# ---- Outreach-service pitch ----
R.append(("252814911656115","Reporty","Outreach",2,"2026-07-16","2026-07-16 cold pitch offering a targeted-outreach service to bring Reporty (their AI clinic assistant) more clinic clients; their own AI agent 'Maha' auto-replied and said it would forward to a specialist","cold-sent — replied by their AI bot, awaiting a human","Await Reporty's specialist / re-touch."))

# Skips (recorded here for the tally, not written):
SKIPS = [
    ("253811209818318", "inbound wrong-number ('رقم غلط'), no outreach — personal/non-campaign"),
    ("278498765758494", "inbound only (image+doc+'ريڤال'), no cold message from Ahmed — unclassifiable"),
]

def build(peer, name, camp, imp, when, arc, stage, nxt):
    disp = name if name else f"+{peer}"
    ent_name = name if name else f"+{peer}"
    text = (f"WhatsApp lead +{peer} ({disp}) — {CAMP[camp]} cold outreach from "
            f"Ahmed's WA +{ACCT}: {arc}. STOPPED AT: {stage}. {nxt}")
    return {
        "text": text,
        "kind": "fact",
        "when": when,
        "importance": imp,
        "confidence": 0.8,
        "source": "wa-backfill",
        "group": "ahmed",
        "entities": [{"name": ent_name}, {"name": CAMP_ENTITY[camp]}],
    }

def main():
    dry = os.environ.get("DRY_RUN") == "1"
    key = None if dry else load_key()
    # de-dupe by peer (last write wins) to guard against accidental doubles
    seen = {}
    order = []
    for rec in R:
        peer = rec[0]
        if peer not in seen:
            order.append(peer)
        seen[peer] = rec
    payloads = [build(*seen[p]) for p in order]

    print(f"records={len(payloads)} skips={len(SKIPS)} total={len(payloads)+len(SKIPS)}")
    # campaign tally
    tally = {}
    for p in order:
        c = seen[p][2]
        tally[c] = tally.get(c, 0) + 1
    print("campaigns:", json.dumps(tally))
    if dry:
        for pl in payloads[:4]:
            print(json.dumps(pl, ensure_ascii=False))
        return

    off = int(os.environ.get("OFFSET", "0"))
    lim = int(os.environ.get("LIMIT", str(len(payloads))))
    batch = payloads[off:off+lim]
    print(f"posting {len(batch)} (offset={off})")
    ok = 0
    fail = 0
    for pl in batch:
        body = json.dumps(pl, ensure_ascii=False).encode("utf-8")
        req = urllib.request.Request(f"{BASE}/remember", data=body, method="POST",
            headers={"Content-Type": "application/json", "Authorization": f"Bearer {key}"})
        try:
            with urllib.request.urlopen(req, timeout=30) as r:
                r.read()
                ok += 1
        except urllib.error.HTTPError as e:
            fail += 1
            print(f"FAIL {pl['entities'][0]['name']}: HTTP {e.code} {e.read()[:200]!r}")
        except Exception as e:
            fail += 1
            print(f"FAIL {pl['entities'][0]['name']}: {type(e).__name__} {e}")
        time.sleep(0.15)
    print(f"written={ok} failed={fail}")

if __name__ == "__main__":
    main()
