#!/usr/bin/env python3
"""2026-10-16 run: originals-only dormancy, offer grep, window/RT checks.

KEY SHAPES (relearned 2026-10-11):
  qualifying[] keys: handle, score, date, likes, rt, replies, views, text, url
  raw[handle][] keys: userName, likeCount, retweetCount, replyCount, viewCount,
                      createdAt, text, retweeted_tweet, type, id
Filtering buckets by `retweeted_tweet` on `qualifying` ALWAYS passes (key absent).
The RT check must run against raw[handle][].
"""
import json, re
from datetime import datetime, timezone, timedelta

DATE = "2026-10-16"
P = f"/home/kiro/trend-engine/trends/x/raw/scan_results_{DATE}_FULL.json"
d = json.load(open(P))
q = d["qualifying"]
raw = d["raw"]
handles = d["handles"]

now = datetime(2026, 10, 16, 6, 15, tzinfo=timezone.utc)
cutoff = now.replace(hour=0, minute=0, second=0, microsecond=0) - timedelta(days=3)

def pdate(s):
    try:
        return datetime.strptime(s, "%a %b %d %H:%M:%S %z %Y")
    except Exception:
        return None

def is_orig(t):
    return (not t.get("retweeted_tweet")) and t.get("type") != "retweet" \
        and not (t.get("text") or "").startswith("RT @")

print(f"### CUTOFF {cutoff.isoformat()}  | scanned {len(handles)} | failures {len(d['failures'])}")
print(f"### qualifying {len(q)} ({len({x['handle'] for x in q})} handles)")

# ---------- 1. HANDLE DIFF vs 10-15 ----------
prev = json.load(open("/home/kiro/trend-engine/trends/x/raw/scan_results_2026-10-15_FULL.json"))
ph, ch = set(prev["handles"]), set(handles)
print(f"\n### HANDLE DIFF vs 10-15: was {len(ph)} now {len(ch)}")
print("ADDED:", sorted(ch - ph) or "(none)")
print("REMOVED:", sorted(ph - ch) or "(none)")

# ---------- 2. DORMANCY (originals only) ----------
core_buckets = {x["handle"] for x in q}
print("\n### DORMANCY -- zero-qualifying handles, newest ORIGINAL vs cutoff")
for h in handles:
    if h in core_buckets:
        continue
    tw = raw.get(h, [])
    if not tw:
        print(f"@{h}: NO RAW DATA")
        continue
    origs = [t for t in tw if is_orig(t)]
    allrts = len(tw) - len(origs)
    newest_orig = max((pdate(t.get("createdAt", "")) for t in origs), default=None)
    if newest_orig is None:
        print(f"@{h}: 0 originals in {len(tw)} fetched (RT-only)")
        continue
    age = (now - newest_orig).days
    inwin_orig = [t for t in origs if pdate(t.get("createdAt", "")) and pdate(t.get("createdAt", "")) >= cutoff]
    verdict = "IN-WINDOW -> genuine threshold artefact" if inwin_orig else f"OUT-OF-WINDOW ({age}d)"
    best = ""
    if inwin_orig:
        b = max(inwin_orig, key=lambda t: (t.get("likeCount") or 0) + (t.get("viewCount") or 0) / 100)
        best = f" best in-window orig {b.get('likeCount')}L/{(b.get('viewCount') or 0)}V"
    print(f"@{h}: newest orig {newest_orig.strftime('%Y-%m-%d %H:%M')} ({age}d) | "
          f"orig {len(origs)} / RT {allrts} | {verdict}{best}")

# ---------- 3. WINDOW ROLL-OFF per handle (count=5 is a no-op) ----------
print("\n### FETCH WINDOW: oldest fetched tweet per high-frequency handle")
for h in ["higgsfield_ai", "higgsfield", "Flovaai", "AIWarper", "runwayml", "Kling_ai",
          "EHuanglu", "CharaspowerAI", "c_valenzuelab", "venturetwins"]:
    tw = raw.get(h, [])
    ds = [pdate(t.get("createdAt", "")) for t in tw]
    ds = [x for x in ds if x]
    if not ds:
        continue
    oldest = min(ds)
    inside = oldest >= cutoff
    print(f"@{h}: {len(tw)} fetched | oldest {oldest.strftime('%Y-%m-%d %H:%M')} | "
          f"{'WINDOW FULLY INSIDE -> roll-off risk' if inside else 'spans before cutoff'}")

# ---------- 4. OFFER / ARBITRAGE GREP on qualifying text ----------
OFFERS = {
    "Flova Seedance 80%/365d lock": r"80%|365[- ]day|rate lock",
    "Magnific One": r"magnific",
    "Magnific UNLIMITED": r"unlimited.{0,25}magnific|magnific.{0,25}unlimited",
    "Dreamina Originals": r"dreamina originals|originals program",
    "Dolphin AI XX-AYCMR8": r"XX-AYCMR8|dolphin ai",
    "Higgsfield cashback": r"cashback|cash back",
    "Higgsfield Ads Studio": r"ads studio|ad multiplier",
    "Higgsfield Genjutsu API": r"genjutsu",
    "Higgsfield AI Influencer": r"ai[- ]influencer",
    "Higgsfield Wan 3.0": r"wan ?3\.0|wan3",
    "Higgsfield API discount": r"\bAPI\b.{0,40}(off|discount)|(60|50)% off",
    "CapCut Black Friday": r"black friday|capcut",
    "filmera": r"filmera",
    "Agent Forge / ACN GPU": r"agent forge|\bACN\b",
    "Air unlimited (offer phrase)": r"unlimited credits|air.{0,20}free",
    "Kling 4.0": r"kling ?4\.0",
    "FLUX 3": r"flux ?3",
    "Nano Banana": r"nano ?banana",
    "free credits / free generations": r"free (credits?|generations?|trial)|credits free|\$\d+ (credit|free)",
    "signup / referral / code": r"referral|invite code|\bfpr=|sign ?up",
    "discount %": r"\b\d{2}% ?off|up to \d{2}%",
    "days left / expires": r"\d+ days? left|expires|until oct|ends oct",
}
print("\n### OFFER GREP (qualifying text, all buckets)")
for name, pat in OFFERS.items():
    rx = re.compile(pat, re.I)
    hits = [x for x in q if rx.search(x["text"])]
    if not hits:
        print(f"  {name}: 0")
        continue
    print(f"  {name}: {len(hits)} -- " + "; ".join(
        f"@{x['handle']} {x['likes']}L/{x['views']}V {x['date'][:10]}" for x in hits[:5]))

# ---------- 5. TOP-10 cutoff + non-core arrival check ----------
CORE_SET = {"runwayml", "CuriousRefuge", "nofilmschool", "venturetwins", "Kling_ai",
            "paultrillo", "c_valenzuelab", "karenxcheng", "higgsfield", "pika_labs",
            "EHuanglu", "azed_ai", "JeffSynthesized", "ai_filmmaker", "Magiermogul",
            "WuxiaRocks", "JiamingSuen", "higgsfield_ai", "Chandan_Perla",
            "CharaspowerAI", "AIWarper", "AI__TSUBAKI", "Flovaai", "DiscussingFilm"}
FILM = {"DiscussingFilm", "nofilmschool"}
LABS = {"OpenAI", "AnthropicAI"}
core = sorted([x for x in q if x["handle"] not in FILM and x["handle"] not in LABS
               and x["handle"] in CORE_SET], key=lambda x: -x["score"])
print(f"\n### CORE top-10 cutoff {core[9]['score']:.0f} (rank11 {core[10]['score']:.0f})")
for i, x in enumerate(core[:11], 1):
    flag = "" if x["handle"] in CORE_SET else "  <<< NON-CORE ARRIVAL"
    print(f"{i:2}|@{x['handle']}|{x['score']:.0f}|{x['likes']}L/{x['views']}V|{x['date']}{flag}")

# ---------- 6. Per-handle maxima for CORE handles ----------
print("\n### PER-HANDLE MAX (core, >=3 qualifying)")
from collections import defaultdict
mx = defaultdict(list)
for x in core:
    mx[x["handle"]].append(x)
for h, rows in sorted(mx.items(), key=lambda kv: -max(r["score"] for r in kv[1])):
    if len(rows) < 3:
        continue
    b = max(rows, key=lambda r: r["score"])
    print(f"@{h}: {len(rows)} qual, best {b['score']:.0f} ({b['likes']}L/{b['views']}V) "
          f"{b['date'][:10]} :: {b['text'][:90]}")
