#!/usr/bin/env python3
"""Backfill WhatsApp outreach CRM into jarvis-memory — SLICE 3 of 5 (LIMIT 92 OFFSET 184).
Read-only over whatsapp.db. One fact per lead POSTed to /remember. Run with --dry to preview."""
import sqlite3, os, re, json, sys, time, urllib.request

DB = "/Users/ahmed/devFolder/Ultron/claude-voice/whatsapp-reader/whatsapp.db"
ENV = "/Users/ahmed/devFolder/Ultron/claude-voice/.env"
URL = "https://jarvis-production-3e5f.up.railway.app/remember"
DRY = "--dry" in sys.argv

def api_key():
    for ln in open(ENV, encoding="utf-8"):
        if ln.startswith("MEMORY_API_KEY="):
            return ln.split("=", 1)[1].strip()
    raise SystemExit("no MEMORY_API_KEY")

KEY = api_key()

LEADS = [199935123292295,199978190422228,200072595820759,203654514630696,204810011836471,205497105924153,206545598079027,206833310507109,206901543452840,206927313252602,207820716785681,208074707042510,208211441414189,208537875677420,208851492204755,209044681785369,209568751702081,209645993992410,210630128750696,211583041036426,212588147245062,213176910147834,213240948748289,213382615531689,213593035403320,213902541492477,214082846212105,214323330822327,215044767895799,215362880712889,215539108601952,215723959910588,216225867120873,216316631842924,217286707281971,217437165359114,217454965964888,217724978499823,218334779945028,219653284573341,220048404791423,220559539441693,221157026463933,221397125169398,221465878233185,221543036625149,222397819027686,222814330196078,222827684855903,223166685311141,223484579950593,223978266304680,224467942912252,224468110672117,225623389818916,226603061756146,226722884636873,22746230698184,228595372925035,22939504238829,229518807703590,230751496831051,230755808620565,230828806279330,231830104092682,232138905485498,232886414381211,233380033654885,233934017290449,234715785248777,235334260535438,23575209730179,235841586769936,236442664071210,238521612812364,238959313555710,239951903998149,240754928656438,240780211933386,240848914657386,241471768817785,241566325166285,241909805109258,243537849409682,243619202072659,243902669971579,244525490553007,244843351666800,245831093498028,246234837164268,246858261778553,247863216967758]

# person name (from the cold-message greeting), None if unknown
NAMES = {
 "199935123292295":"Abdulaziz","199978190422228":"Raghad","200072595820759":"Osama Alshuail",
 "203654514630696":"Yousef","204810011836471":"Ali","205497105924153":"May","206901543452840":"Hamzah",
 "206927313252602":"Faisal","207820716785681":"Hussein","208211441414189":"Ali","208537875677420":"Abdulmohsen",
 "208851492204755":"Afaf","209044681785369":"Ali","209568751702081":"Rahaf","211583041036426":"Essa",
 "212588147245062":"Ahmed","213240948748289":"Mohamed","213382615531689":"Sameh Madi","213593035403320":"Mohammad",
 "214323330822327":"Yousef","215044767895799":"Talal","216225867120873":"Abdulkarim","217286707281971":"Mesnad",
 "217437165359114":"Naif","217724978499823":"Mohamed","218334779945028":"Mohammed","219653284573341":"Bader Alturki",
 "220048404791423":"Sohyb Alblushi","220559539441693":"Abdullah","221397125169398":"Ibtissam","221465878233185":"Saad",
 "222397819027686":"Abdullah","223484579950593":"Ramy","223978266304680":"Khaled","225623389818916":"Adnan",
 "226722884636873":"Abdulrhman","228595372925035":"Ahmed","22939504238829":"Abdullah","229518807703590":"Nariman",
 "230751496831051":"Ahmed","230755808620565":"Hajer","230828806279330":"Mohammed","233380033654885":"Nouf",
 "233934017290449":"Abdullah","234715785248777":"Maha","235334260535438":"Khalid","23575209730179":"Mojahed",
 "238959313555710":"Marwan","240780211933386":"Waad","240848914657386":"Ahmed","241471768817785":"Abdulrhman",
 "241566325166285":"Shehab","241909805109258":"Mahmoud","243619202072659":"Shehroz","243902669971579":"Fahad",
 "244525490553007":"Mirza","245831093498028":"Luigi","246234837164268":"Ahmed","246858261778553":"Shahad",
}
# business name (from auto-reply) when the person name is unknown / for context
BIZ = {
 "200072595820759":"Soudah Development","206833310507109":"Gustoa Pasta","209645993992410":"Bonble Bakery",
 "210630128750696":"Olick Coffee","213176910147834":"Tuwallad","213382615531689":"Food Sources Trading Co",
 "213902541492477":"Al Fanar Coffee","214082846212105":"Tamriyah Al Jouri (goorreey)","215539108601952":"Fairmont Riyadh",
 "216316631842924":"ELDER","219653284573341":"Amiral Saudi Arabia","220048404791423":"Half Million",
 "221543036625149":"LA Lounge","222827684855903":"La Rio","226603061756146":"Madad Coffee","231830104092682":"Kookh Safana",
 "235841586769936":"Coplant",
}

CAMP_DESC = {
 "reval_games":"Reval corporate/team-building video-game (employees become in-game characters, World-Cup / entertainment-day)",
 "reval_content":"Reval social-media/content agency (cafes & restaurants)",
 "reval_design":"Reval free-design offer (Instagram/social posts)",
 "ain":"AIN (عين / tryain) AI camera-monitoring — turns existing CCTV into a live operations brain",
 "job":"Ahmed Alrajeh's job/CV outreach (offers to build a working product for a role)",
 "dinosaur":"Dinosaur (ديناصور) coffee-prepay platform",
}
CAMP_ENT = {"reval_games":"Reval","reval_content":"Reval","reval_design":"Reval",
            "ain":"AIN (عين)","job":"Ahmed job outreach","dinosaur":"Dinosaur (ديناصور)"}

def classify(cold_text):
    j = cold_text
    if "ديناصور" in j: return "dinosaur"
    if "نحط موظفين" in j or "ألعاب مخصصة" in j or "لعبة فيديو" in j: return "reval_games"
    if "أثبت نفسي عمليًا" in j or "فرصة وظيفية" in j: return "job"
    if "عين" in j and ("كاميرات" in j or "فريق عين" in j or "من عين" in j): return "ain"
    if "نحول المحتوى" in j or "Reval Agency" in j or "السوشيال ميديا" in j: return "reval_content"
    if "تصميم مجانا" in j: return "reval_design"
    return None

# hand-authored arcs/stages for engaged or nuanced leads
OV = {
 "199935123292295":(3,"cold games pitch 2026-06-17; Abdulaziz replied same day — no events on now but asked how it works and the fees; Ahmed explained a 2–4h interactive World-Cup-style experience priced by headcount and sent the Al Rugaib example",
   "replied — engaged, asked details, no event scheduled","Follow up when they have an employee event."),
 "200072595820759":(4,"cold 06-17→06-19; Osama said 'send it', Ahmed sent the portfolio + World-Cup games deck (cited Ithra, Avalon Pharma, Al Rugaib as clients); 06-29 Ahmed offered a custom proposal, Osama agreed and gave email oshuail.t@soudah.sa",
   "interested — gave work email, awaiting a custom proposal","Send a tailored proposal to oshuail.t@soudah.sa (Soudah Development)."),
 "203654514630696":(4,"cold 07-15; Yousef asked for the offer file and pricing, Ahmed sent the deck and asked branch/camera counts — Yousef has 16 cameras across 1 branch; Ahmed proposed a demo meeting, Yousef wants the quote first",
   "interested — quote pending then ops demo (16 cameras / 1 branch)","Send the price quote, then schedule the operations demo."),
 "205497105924153":(3,"cold 07-07; May said they already started the camera idea with another company and are now hunting AI customer-service agents (WhatsApp + social, where most CS load sits); conversation pivoted, Ahmed probing their WhatsApp tooling",
   "replied — passed on cameras, open to AI customer-service (WhatsApp/social)","Pitch an AI WhatsApp/social customer-service agent instead of cameras."),
 "213240948748289":(3,"cold 07-15; Mohamed asked for the offer file, Ahmed sent it (first copy arrived blank, resent)",
   "replied — requested and received the offer file","Follow up on the offer."),
 "213593035403320":(4,"cold 07-15; Mohammad engaged hard — asked the company name (عين), compared us to competitor 'رايم', asked price and differentiators; Ahmed pitched a lower price that drops with more branches and a custom-trained on-prem AI model; Mohammad asked for a video + offer file, Ahmed sent the deck (no video yet) and offered a live demo",
   "interested — offer sent, live demo pending","Arrange the live demo; no video asset exists yet."),
 "214082846212105":(3,"cold free-design offer 04-16 to Tamriyah Al Jouri (goorreey); they asked 'design of what?', Ahmed said Instagram/social posts and sent sample work; 04-17 they asked for design pricing",
   "interested — asked for design pricing","Send a design price list."),
 "214323330822327":(3,"cold job/CV pitch 07-02; Yousef replied 07-15 he'll keep the CV on file for future openings",
   "declined politely — CV kept for future vacancies","Re-check when they post a role."),
 "217454965964888":(4,"after a phone call on 07-15 Ahmed sent a video explaining the Dinosaur (ديناصور) platform — we prepay the cafe for coffee (reserve stock), subscribers redeem via an app barcode; she loved it and asked for the contract and price; Ahmed quoted a no-contract trial invoice, min 20 cups, ~20% discount off the normal price",
   "interested — pricing/terms sent, awaiting decision","Close on cup count and issue the trial invoice."),
 "217724978499823":(3,"cold 07-07; Mohamed replied 07-10 asking for the brochure, Ahmed sent it",
   "replied — brochure sent","Follow up on the brochure."),
 "220559539441693":(4,"cold 07-15; Abdullah said 'excellent, send the offer', Ahmed sent the deck; Abdullah asked when they can have a call, Ahmed gave 0544067114 for anytime",
   "interested — call to be scheduled (number shared)","Take/confirm the call on 0544067114."),
 "221465878233185":(2,"cold games pitch 06-17; Saad only asked 'who is this?', Ahmed identified himself (Ahmed Alrajeh, Reval Agency); no further engagement",
   "replied — asked identity only, then silent","Re-approach with the portfolio."),
 "223166685311141":(3,"after a call on 07-15 Ahmed sent the Dinosaur (ديناصور) intro video + prepay-platform explanation; no reply yet",
   "post-call follow-up sent, awaiting reply","Follow up on the Dinosaur video."),
}

SKIP = {"244843351666800"}  # empty cold opener, no classifiable campaign (needs-transcript)

AUTO_HINT = ("شكرا لك على تواصل","شكراً على تواصل","Thank you for contacting","نحن لسنا متوفر","غير متوفر",
             "سيتم الرد","يرجى إخبارنا","Welcome to","أهلًا بك في","خدمة عملاء","teşekkür","شات بوت","سعيد بخدمتك",
             "أهلاً وسهلاً","اوقات العمل","أوقات عمل","لطلب من رابط")

con = sqlite3.connect(DB); con.row_factory = sqlite3.Row

def thread(p):
    return con.execute("SELECT from_me,account,body,media_type,datetime(ts/1000,'unixepoch') AS t "
                       "FROM messages WHERE is_group=0 AND peer_number=? ORDER BY ts", (p,)).fetchall()

def post(payload):
    data = json.dumps(payload).encode("utf-8")
    req = urllib.request.Request(URL, data=data, method="POST",
        headers={"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"})
    with urllib.request.urlopen(req, timeout=45) as r:
        return r.status, r.read(200).decode("utf-8", "replace")

processed = written = 0
skips = {"needs_transcript":0, "personal":0, "otp":0, "unknown":0}
camps = {}
samples = []

for pid in LEADS:
    p = str(pid); processed += 1
    rows = thread(p)
    if p in SKIP:
        skips["needs_transcript"] += 1
        print(f"SKIP {p} needs-transcript (empty cold opener)"); continue
    cold_join = " ".join(r["body"] or "" for r in rows if r["from_me"] == 1)
    camp = classify(cold_join)
    if not camp:
        skips["unknown"] += 1
        print(f"SKIP {p} unknown campaign"); continue
    account = next((r["account"] for r in rows if r["account"]), "966565625560")
    when = rows[-1]["t"].split(" ")[0]
    name = NAMES.get(p) or BIZ.get(p) or "unknown"
    ent_name = NAMES.get(p) or BIZ.get(p) or f"+{p}"
    peer_real = [r for r in rows if r["from_me"] == 0 and (r["body"] or "").strip()]
    peer_auto = any(any(h in (r["body"] or "") for h in AUTO_HINT) for r in peer_real)

    if p in OV:
        imp, arc, stage, nxt = OV[p]
    else:
        first_dt = rows[0]["t"].split(" ")[0]
        biz = BIZ.get(p)
        arc = f"cold {CAMP_ENT[camp].split(' (')[0]} pitch sent {first_dt}"
        if biz: arc += f" to {biz}"
        if peer_auto:
            imp, stage, nxt = 2, "cold-sent, business auto-reply only", "No human reply yet."
            arc += "; only the business auto-responder replied"
        else:
            imp, stage, nxt = 2, "cold-sent, no reply", "No engagement yet."

    text = (f"WhatsApp lead +{p} ({name}) — {CAMP_DESC[camp]} cold outreach from Ahmed's WA +{account}: "
            f"{arc}. STOPPED AT: {stage}. {nxt}")
    payload = {"text": text, "kind": "fact", "when": when, "importance": imp, "confidence": 0.8,
               "source": "wa-backfill", "group": "ahmed",
               "entities": [{"name": ent_name}, {"name": CAMP_ENT[camp]}]}
    ck = CAMP_ENT[camp] + ("/games" if camp=="reval_games" else "/content" if camp=="reval_content"
          else "/design" if camp=="reval_design" else "")
    camps[ck] = camps.get(ck, 0) + 1

    if DRY:
        print(json.dumps(payload, ensure_ascii=False))
    else:
        try:
            st, body = post(payload)
            if st >= 300:
                print(f"ERR {p} HTTP {st} {body}"); continue
        except Exception as e:
            print(f"ERR {p} {e}"); continue
    written += 1
    if len(samples) < 4 and (imp >= 3):
        samples.append(text)
    time.sleep(0.15)

print("\n==== SUMMARY ====")
print("processed:", processed, "written:", written, "skips:", skips)
print("campaigns:", json.dumps(camps, ensure_ascii=False))
print("\n---- 4 samples ----")
for s in samples: print("-", s)
