#!/usr/bin/env python3
"""
active-channels.py — Identify active Discord channels (last 2 days).
Used by heartbeat to skip scanning dead channels and avoid wasting tokens.

Usage:
  python3 active-channels.py              # Print active channels
  python3 active-channels.py --json       # JSON output for scripting
  python3 active-channels.py --all        # Show all channels with status
  python3 active-channels.py --days 2     # Custom threshold (default: 2)
"""

import os
import sys
import json
import time
import argparse
import requests
from datetime import datetime, timezone, timedelta

GUILD_ID = "1467974388581273603"
BOT_TOKEN = os.environ.get("DISCORD_BOT_TOKEN", "")
USER_TOKEN = os.environ.get("DISCORD_USER_TOKEN", "")

# Use bot token if available, else user token
TOKEN = BOT_TOKEN or USER_TOKEN
if not TOKEN:
    # Try reading from openclaw config
    import subprocess
    try:
        result = subprocess.run(
            ["openclaw", "config", "get", "discord.token"],
            capture_output=True, text=True
        )
        TOKEN = result.stdout.strip()
    except Exception:
        pass

HEADERS = {"Authorization": f"Bot {TOKEN}" if BOT_TOKEN else TOKEN}

SKIP_CHANNEL_TYPES = {4}  # Category channels — skip entirely

def get_channels():
    url = f"https://discord.com/api/v10/guilds/{GUILD_ID}/channels"
    r = requests.get(url, headers=HEADERS)
    r.raise_for_status()
    return r.json()

def snowflake_to_datetime(snowflake_id: str) -> datetime:
    """Convert Discord snowflake ID to UTC datetime."""
    ts = (int(snowflake_id) >> 22) + 1420070400000
    return datetime.fromtimestamp(ts / 1000, tz=timezone.utc)

def get_last_message_time(channel) -> datetime | None:
    last_msg_id = channel.get("last_message_id")
    if not last_msg_id:
        return None
    return snowflake_to_datetime(last_msg_id)

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--json", action="store_true", help="JSON output")
    parser.add_argument("--all", action="store_true", help="Show all channels")
    parser.add_argument("--days", type=float, default=2.0, help="Inactivity threshold in days")
    args = parser.parse_args()

    threshold = timedelta(days=args.days)
    now = datetime.now(tz=timezone.utc)
    cutoff = now - threshold

    channels = get_channels()
    results = []

    for ch in channels:
        if ch["type"] in SKIP_CHANNEL_TYPES:
            continue

        name = ch.get("name", "unknown")
        ch_id = ch["id"]
        last_time = get_last_message_time(ch)

        if last_time is None:
            age_str = "never"
            active = False
        else:
            age = now - last_time
            age_str = f"{age.days}d {age.seconds // 3600}h ago"
            active = last_time >= cutoff

        results.append({
            "id": ch_id,
            "name": name,
            "active": active,
            "last_message_id": ch.get("last_message_id"),
            "last_activity": last_time.isoformat() if last_time else None,
            "age_str": age_str,
        })

    # Sort: active first, then by recency
    results.sort(key=lambda x: (not x["active"], x["last_activity"] or "0"), reverse=False)
    results.sort(key=lambda x: x["last_activity"] or "0", reverse=True)

    active_channels = [r for r in results if r["active"]]
    inactive_channels = [r for r in results if not r["active"]]

    if args.json:
        print(json.dumps({
            "active": active_channels,
            "inactive": inactive_channels,
            "threshold_days": args.days,
            "generated_at": now.isoformat()
        }, indent=2))
        return

    print(f"\n✅ ACTIVE (last {args.days} days) — {len(active_channels)} channels")
    print("-" * 60)
    for ch in active_channels:
        print(f"  #{ch['name']:<35} {ch['age_str']}")

    if args.all:
        print(f"\n💤 INACTIVE — {len(inactive_channels)} channels")
        print("-" * 60)
        for ch in inactive_channels:
            print(f"  #{ch['name']:<35} {ch['age_str']}")

    print(f"\nTotal: {len(results)} channels | Active: {len(active_channels)} | Inactive: {len(inactive_channels)}")
    print(f"Threshold: {args.days} days | Generated: {now.strftime('%Y-%m-%d %H:%M UTC')}")

if __name__ == "__main__":
    main()
