#!/usr/bin/env python3
"""SLICE 5/5 — WhatsApp outreach CRM backfill into jarvis-memory.
Leads: LIMIT 200 OFFSET 368 (the tail, 89 peers). READ-ONLY on whatsapp.db.
DRY_RUN=1 prints payloads; otherwise POSTs to /remember."""
import sqlite3, json, re, os, sys, urllib.request

DB = os.path.join(os.path.dirname(os.path.abspath(__file__)), "whatsapp.db")
API = "https://jarvis-production-3e5f.up.railway.app/remember"
ENV = "/Users/ahmed/devFolder/Ultron/claude-voice/.env"
DRY = os.environ.get("DRY_RUN") == "1"

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

KEY = api_key()
ACCT = "966565625560"

CAMP = {
    "AIN":  "AIN (عين cameras)",
    "REVAL": "Reval",
    "JOB":  "Ahmed Alrajeh job search",
    "DINO": "Dinosaur (coffee prepay)",
}

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

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

def peers():
    rows = con.execute(
        "SELECT peer_number FROM (SELECT DISTINCT peer_number FROM messages "
        "WHERE is_group=0 AND peer_number IS NOT NULL ORDER BY peer_number) "
        "LIMIT 200 OFFSET 368").fetchall()
    return [r[0] for r in rows]

def cold_of(rows):
    return next((r["body"] for r in rows if r["from_me"] == 1 and r["body"] and r["body"].strip()), "")

def name_of(cold, push):
    for pat in [r'أ\.\s*([^\n👋]{1,30}?)\s*(?:👋|\n)',
                r'السلام عليكم\s+([A-Za-z][^،\n]{1,30}?)[،\n]',
                r'السلام عليكم\s+([^\n]{1,25}?)\s+معاك أحمد',
                r'هلا\s+([^،\n👋]{1,25}?)[،\s]*(?:كيف حالك|👋)']:
        m = re.search(pat, cold or "")
        if m:
            return m.group(1).strip()
    return (push or "").strip()

def classify(cold):
    c = cold or ""
    if "عين" in c or "كاميرات" in c or "المراقبة" in c:
        return "AIN"
    if "أحمد الراجح" in c and "أثبت نفسي" in c:
        return "JOB"
    if "ديناصور" in c:
        return "DINO"
    return "REVAL"  # design / games / content agency / outreach service — all Reval

def reval_flavor(c):
    if "لعبة" in c or "موظفينك" in c:
        return "Reval corporate-games / team-building"
    if "تصميم مجانا" in c:
        return "Reval free-design"
    if "بهاء" in c or "Outreach" in c or "تواصل مستهدف" in c:
        return "Reval targeted-outreach service"
    return "Reval content / social-media agency"

def ain_flavor(c):
    if "ندوّر شريك" in c or "شريك" in c:
        return "AIN (عين) reseller-partner recruitment"
    return "AIN (عين) CCTV-analytics"

# ---- manual overrides for reply threads + special cases ----
# each: (name, campkey, flavor_text, stage, extra, importance)
M = {
 "47279050354773": ("Ghazi","AIN","AIN (عين) CCTV-analytics",
    "2026-07-15 sent AIN camera pitch; the recipient's auto-responder acknowledged and said it would forward the request to the specialized team",
    "replied (auto-forward to team)","awaiting a human callback",3),
 "47584278253818": ("Mohammad bin Abdullah (Lawnain ad agency, Al-Sulayyil)","REVAL","Reval free-design",
    "2026-04-16 free-design cold pitch to Lawnain advertising agency (وكالة لونين, محافظة السليل); they declined (already have 4 in-house designers), talk pivoted to Ahmed offering a remote female designer to cover a vacation but they needed an on-site male for printing/acrylic so it fell through; they saved Ahmed's contact (Reval — Ahmed Alrajeh) for future design overflow",
    "declined","goodwill kept — they saved his number for future overflow work",3),
 "49577008865318": ("Ali","JOB","Ahmed's job/prove-myself pitch",
    "2026-07-02 job cold pitch; company auto-responder replied and confirmed it was forwarded to the relevant department",
    "cold-sent, auto-forwarded to department","awaiting department response",2),
 "59949304561724": ("Elie","JOB","Ahmed's job/prove-myself pitch",
    "2026-07-01 job cold pitch; Elie replied he forwarded the CV to HR who would contact Ahmed very soon",
    "referred -> HR","awaiting HR contact",4),
 "60949998383138": ("Raiman","REVAL","Reval corporate-games / team-building",
    "2026-06-17 Reval custom-games pitch (two games: light Street-Fighter-style combat + a football one); Raiman asked for the portfolio, Ahmed sent it plus a sample of a custom employee-character game built for Al-Ruqaib Furnishings (مفروشات الرقيب)",
    "interested, portfolio sent","awaiting Raiman's reply",4),
 "61856538427618": ("+61856538427618","REVAL","Reval content / free-design",
    "2026-04-15/16 Reval content pitch then free-design offer; recipient replied 'we'd be honored' (نتشرف بذلك), agreeing to receive a free design sample",
    "interested (agreed to receive a free design)","Ahmed to deliver the sample design",3),
 "63406619009187": ("Sarah (سارة)","REVAL","Reval corporate-games / team-building",
    "2026-06-17 Reval custom-games pitch; Sarah welcomed it and said the responsible employee would contact Ahmed",
    "referred -> responsible staffer","awaiting the staffer's call",4),
 "65283603623971": ("Mohammad","AIN","AIN (عين) CCTV-analytics",
    "2026-07-07 AIN camera pitch; Mohammad replied warmly, shared a contact card, and asked Ahmed to reach out to the operations manager",
    "referred -> operations manager","Ahmed to contact the ops manager (card shared)",4),
 "69320973488380": ("Yaser","JOB","Ahmed's job/prove-myself pitch",
    "2026-07-02 job cold pitch; Yaser replied there's no need currently (small company, already overstaffed); Ahmed re-pinged 2026-07-15 with no reply",
    "declined (no vacancy)","closed",3),
 "79324472451140": ("+79324472451140 (meat moot)","REVAL","Reval free-design",
    "2026-04-16 free-design cold pitch; only the business WhatsApp auto-greeting (meat moot) replied",
    "cold-sent, auto-reply only","no human engagement",2),
 "80299044155517": ("+80299044155517 (HASSAN)","REVAL","Reval content / social-media agency",
    "2026-04-07 Reval content pitch; only the business WhatsApp auto-greeting (HASSAN) replied",
    "cold-sent, auto-reply only","no human engagement",2),
 "87196577079418": ("Khalid","AIN","AIN (عين) CCTV-analytics",
    "2026-07-15 AIN camera pitch; Khalid asked for an intro video, Ahmed sent the portfolio document and offered a quick demo meeting; Khalid said he'd take a look and Ahmed asked what time suits",
    "interested, demo/meeting proposed","awaiting Khalid to pick a meeting time",4),
 "87651843588227": ("+87651843588227 (Jihad shaikh)","AIN","AIN (عين) CCTV-analytics",
    "2026-07-15 AIN camera pitch; only the WhatsApp business auto-greeting (Jihad shaikh) replied",
    "cold-sent, auto-reply only","no human engagement",2),
 "88356117590089": ("Rawan","JOB","Ahmed's job/prove-myself pitch",
    "2026-07-02 job cold pitch; Rawan engaged, asked Ahmed's specialty (Software Engineer), and said she'd send the CV to their operations manager and contact him if the department has a need",
    "interested, referred -> operations manager","awaiting whether the dept has a need",4),
 "92857360769269": ("+92857360769269 (Milan cafe/restaurant)","REVAL","Reval free-design",
    "2026-04-16 free-design cold pitch; only the Milan café/restaurant WhatsApp auto-greeting replied",
    "cold-sent, auto-reply only","no human engagement",2),
 "95859442188506": ("Al-Bahyan Majalis (مجالس البهيان)","REVAL","Reval free-design",
    "2026-04-16 free-design cold pitch to Al-Bahyan Majalis; they engaged and twice asked what the company does; Ahmed explained Reval designs for cafes/restaurants and grows Instagram — a niche mismatch since they're a majalis (seating) business, they pushed back ('you'll design the majalis? let me see if I'd benefit') and Ahmed apologized for the intrusion",
    "replied then declined (niche mismatch)","closed",3),
 "97577563344933": ("Faisal","AIN","AIN (عين) CCTV-analytics",
    "2026-07-13 AIN camera pitch; Faisal replied warmly on 2026-07-14 that when he's back in Riyadh they'll be in touch",
    "interested, deferred","reconnect when Faisal returns to Riyadh",3),
 "98810420314138": ("+98810420314138 (Coffee JEWELS)","REVAL","Reval content / social-media agency",
    "2026-04-07 Reval content pitch; only the coffee shop's WhatsApp auto-greeting (Coffee JEWELS) replied with its catalog link",
    "cold-sent, auto-reply only","no human engagement",2),
 # special non-cold-send / distinct venture
 "6988683542764": ("+6988683542764","DINO","Dinosaur (ديناصور) coffee-prepay platform",
    "2026-07-15 post-call follow-up for the Dinosaur platform — Ahmed pre-pays for the shop's coffee stock and app subscribers redeem cups via a barcode; sent a short explainer video after a phone call",
    "post-call, video sent","awaiting the owner's decision on cup volume",3),
 "95138525216775": ("+95138525216775 (Baha salon system)","REVAL","Reval targeted-outreach service",
    "2026-07-16 targeted-outreach (Outreach) service pitch to Baha salon-management software (نظام بهاء لإدارة الصالونات) offering to bring them more customers; no reply",
    "cold-sent, no reply","follow up",2),
}

SKIP = {"966565625560"}  # self/account number, zero-text (all media/empty) -> needs-transcript

def build(p):
    rows = thread(p)
    cold = cold_of(rows)
    push = next((r["push_name"] for r in rows if r["push_name"]), "")
    when = rows[-1]["t"][:10] if rows else ""
    them = sum(1 for r in rows if r["from_me"] == 0)
    if p in M:
        name, ck, flav, arc, stage, extra, imp = M[p]
    else:
        ck = classify(cold)
        nm = name_of(cold, push)
        name = nm if nm else "+"+p
        if ck == "AIN":
            flav = ain_flavor(cold)
        elif ck == "REVAL":
            flav = reval_flavor(cold)
        elif ck == "JOB":
            flav = "Ahmed's job/prove-myself pitch"
        else:
            flav = CAMP[ck]
        arc = f"{when} sent the {flav} cold message; no reply"
        stage = "cold-sent, no reply"
        extra = "follow up"
        imp = 2
    if name.startswith("+") and "(" in name:              # "+peer (Business)" -> use the label
        label = name[name.index("(")+1:name.rindex(")")]
        disp, ent_lead = label, label
    elif name == "+"+p:                                    # phone-only, no name known
        disp, ent_lead = "unknown", "+"+p
    else:                                                  # real contact name
        disp, ent_lead = name, name
    text = (f"WhatsApp lead +{p} ({disp}) — {flav} cold outreach from Ahmed's WA +{ACCT}: "
            f"{arc}. STOPPED AT: {stage}. {extra}.")
    payload = {
        "text": text,
        "kind": "fact",
        "when": when,
        "importance": imp,
        "confidence": 0.8,
        "source": "wa-backfill",
        "group": "ahmed",
        "entities": [{"name": ent_lead}, {"name": CAMP[ck]}],
    }
    return ck, payload

def post(payload):
    req = urllib.request.Request(API, data=json.dumps(payload).encode("utf-8"),
        headers={"Content-Type": "application/json", "Authorization": "Bearer "+KEY})
    with urllib.request.urlopen(req, timeout=30) as r:
        return r.status

def main():
    ps = peers()
    written = 0
    skips = {}
    camps = {}
    samples = []
    for p in ps:
        if p in SKIP:
            skips["zero-text/self"] = skips.get("zero-text/self", 0) + 1
            continue
        ck, payload = build(p)
        camps[ck] = camps.get(ck, 0) + 1
        if DRY:
            print(json.dumps(payload, ensure_ascii=False))
        else:
            st = post(payload)
            if st not in (200, 201):
                print("FAIL", p, st, file=sys.stderr)
                continue
        written += 1
        if len(samples) < 4 and p in M and payload["importance"] >= 3:
            samples.append(payload["text"])
    print("---SUMMARY---")
    print("processed:", len(ps))
    print("written:", written)
    print("skips:", skips)
    print("campaigns:", camps)
    for s in samples:
        print("SAMPLE:", s)

if __name__ == "__main__":
    main()
