#!/usr/bin/env python3
"""2026-10-06: retry failed handles, merge into scan_results JSON, dormancy check."""
import os, json, time, sys
import requests
from datetime import datetime, timezone, timedelta

DATE = "2026-10-06"
RAW = "/home/kiro/trend-engine/trends/x/raw"
JSON = f"{RAW}/scan_results_{DATE}_FULL.json"

env_path = os.path.expanduser("~/.hermes/.env")
API_KEY = None
with open(env_path) as f:
    for line in f:
        if line.startswith("GETXAPI_KEY="):
            API_KEY = line.strip().split("=", 1)[1]
            break
assert API_KEY, "no GETXAPI_KEY"

d = json.load(open(JSON))

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

def score(t):
    return ((t.get("likeCount") or 0) + 2 * (t.get("retweetCount") or 0)
            + 3 * (t.get("replyCount") or 0) + (t.get("viewCount") or 0) / 100)

def qualifies(t):
    return ((t.get("likeCount") or 0) >= 50 or (t.get("retweetCount") or 0) >= 10
            or (t.get("viewCount") or 0) >= 1000)

now = datetime.now(timezone.utc)
cutoff = now.replace(hour=0, minute=0, second=0, microsecond=0) - timedelta(days=3)

still_failed = []
for rec in d.get("failures", []):
    h = rec[0] if isinstance(rec, (list, tuple)) else str(rec).split(":")[0].strip().lstrip("@")
    ok = False
    for attempt in range(3):
        try:
            r = requests.get("https://api.getxapi.com/twitter/user/tweets",
                             headers={"Authorization": f"Bearer {API_KEY}"},
                             params={"userName": h, "count": 5}, timeout=60)
            if r.status_code == 200:
                tw = r.json().get("tweets", [])
                d["raw"][h] = tw
                kept = 0
                for t in tw:
                    if t.get("retweeted_tweet") or t.get("type") == "retweet":
                        continue
                    if (t.get("text") or "").startswith("RT @"):
                        continue
                    dt = pdate(t.get("createdAt", ""))
                    if not dt or dt < cutoff or not qualifies(t):
                        continue
                    kept += 1
                    d["qualifying"].append({
                        "handle": h, "score": score(t),
                        "date": dt.strftime("%Y-%m-%d %H:%M UTC"),
                        "likes": t.get("likeCount") or 0,
                        "rt": t.get("retweetCount") or 0,
                        "replies": t.get("replyCount") or 0,
                        "views": t.get("viewCount") or 0,
                        "text": (t.get("text") or "").replace("\n", " ").strip(),
                        "url": f"https://x.com/{h}/status/{t.get('id')}",
                    })
                print(f"RETRY @{h}: recovered {len(tw)} tweets, {kept} qualifying")
                ok = True
                break
            else:
                print(f"RETRY @{h}: HTTP {r.status_code} attempt {attempt+1}")
        except Exception as e:
            print(f"RETRY @{h}: error {e} attempt {attempt+1}")
        time.sleep(3 * (attempt + 1))
    if not ok:
        still_failed.append([h, "retry failed"])
        print(f"RETRY @{h}: STILL FAILING")

d["failures"] = still_failed
d["qualifying"].sort(key=lambda x: x["score"], reverse=True)
json.dump(d, open(JSON, "w"), indent=1)
print("failures remaining:", still_failed)

# --- dormancy check ---
IRRELEVANT = {"AIBuzzNews","AIGuideHQ","AITECHio","AIFrontliner","TheAIColony",
    "AITOPIAai","GoogleLabs","GoogleAI","DonutAI","cladlabs","FaithJaiye2187",
    "KammelaBala","MyStageAI","AlexStudio44","AI_with_jasmin","Ai_Vaidehi",
    "ChrisLaubAI","CINEMA505","OpenAI","AnthropicAI","AIScottAdams"}
active = {x["handle"] for x in d["qualifying"]}
print("\n===== DORMANCY CHECK (zero-qualifying handles) =====")
for h in d["handles"]:
    if h in active:
        continue
    tw = d["raw"].get(h, [])
    dts = [pdate(t.get("createdAt", "")) for t in tw]
    dts = [x for x in dts if x]
    newest = max(dts) if dts else None
    if newest is None:
        print(f"@{h}: NO FETCHED TWEETS (irrelevant={h in IRRELEVANT})")
        continue
    age = (now - newest).days
    verdict = "IN-WINDOW" if newest >= cutoff else "DORMANT"
    tag = "[CORE]" if h not in IRRELEVANT else "[irrelevant]"
    print(f"{tag} @{h}: newest={newest.strftime('%Y-%m-%d')} ({age}d) of {len(tw)} -> {verdict}")
