import json
import logging
import urllib.request
from typing import Dict, Any, Optional
import pandas as pd
from config.loader import CONFIG

TIMEOUT = 10


def _post_json(url: str, payload: Dict[str, Any]) -> bool:
    try:
        req = urllib.request.Request(
            url, data=json.dumps(payload).encode("utf-8"),
            headers={"Content-Type": "application/json"}
        )
        with urllib.request.urlopen(req, timeout=TIMEOUT) as resp:
            return resp.status == 200
    except Exception as e:
        logging.warning(f"Notification delivery failed: {e}")
        return False


def _format_trend(row: pd.Series, rank_change: Optional[int] = None) -> str:
    """Format a single trend alert line."""
    arrow = ""
    if rank_change is not None:
        if rank_change > 0:
            arrow = f" (↑{rank_change})"
        elif rank_change < 0:
            arrow = f" (↓{abs(rank_change)})"
        else:
            arrow = " (—)"

    return (
        f"🚀 #{row['hashtag'].lstrip('#')} — Rank #{int(row.get('rank', 0))}{arrow}\n"
        f"   Weekly velocity: {row.get('weekly_velocity', 0):,.0f} posts/week\n"
        f"   Growth rate: {row.get('growth_rate_pct', 0):.2f}% | "
        f"Acceleration: {row.get('acceleration', 'n/a')} | "
        f"R²: {row.get('r_squared', 0):.3f}"
    )


def send_trend_alerts(
    leaderboard: pd.DataFrame,
    rank_changes: Optional[pd.DataFrame] = None,
    reason: str = "top_k"
) -> bool:
    """
    Send trend alerts via Telegram bot and/or Discord webhook.

    Config-driven: set notifications.telegram_bot_token + telegram_chat_id
    and/or notifications.discord_webhook_url in config.json. Empty = disabled.
    """
    if leaderboard.empty:
        return True

    cfg = CONFIG.get("notifications", {})

    # Build rank change lookup
    change_map = {}
    if rank_changes is not None and not rank_changes.empty:
        for _, r in rank_changes.iterrows():
            change_map[r["tag"]] = int(r.get("rank_change", 0))

    messages = "\n\n".join(
        _format_trend(row, change_map.get(str(row["hashtag"]).lstrip("#")))
        for _, row in leaderboard.iterrows()
    )

    full_text = f"📈 HASHTAG TREND ALERT — {reason}\n\n{messages}"

    ok = True
    token, chat_id = cfg.get("telegram_bot_token"), cfg.get("telegram_chat_id")
    if token and chat_id:
        ok &= _post_json(
            f"https://api.telegram.org/bot{token}/sendMessage",
            {"chat_id": chat_id, "text": full_text, "disable_web_page_preview": True}
        )

    webhook = cfg.get("discord_webhook_url")
    if webhook:
        ok &= _post_json(webhook, {"content": full_text})

    if ok:
        logging.info(f"Trend alerts sent for {len(leaderboard)} hashtag(s) [{reason}].")
    return ok