"""
RugCharts Daily Intelligence Briefing
======================================
THE daily market briefing. AI-researched, AI-written, human-quality.
Published 6:30 AM ET to X (@CryptoRugMunch), Telegram, Ghost CMS.

Pipeline:
  1. Gather - all DataBus sources (prices, news, CT, sentiment, fear/greed, memes)
  2. Research - OpenRouter free model analyzes everything
  3. Write - OpenRouter free model produces the final report
  4. Publish - X/Twitter, Telegram, Ghost CMS

Free models used (zero cost):
  Research: nvidia/nemotron-3-super-120b-a12b:free (1M ctx, 120B MoE)
  Writing:  google/gemma-4-26b-a4b-it:free (262K ctx, excellent prose)
"""

import logging
import os
import re
import subprocess
from datetime import UTC, datetime

import httpx

logger = logging.getLogger("daily_intel")

OPENROUTER_KEY = os.getenv("OPENROUTER_API_KEY", "")
OPENROUTER_URL = "https://openrouter.ai/api/v1/chat/completions"

# Free models for each phase
RESEARCH_MODEL = "nvidia/nemotron-3-super-120b-a12b:free"
WRITING_MODEL = "google/gemma-4-26b-a4b-it:free"
# Fallback if primary unavailable
FALLBACK_RESEARCH = "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free"
FALLBACK_WRITING = "moonshotai/kimi-k2.6:free"

# Publishing targets
X_ACCOUNT = "CryptoRugMunch"
GHOST_URL = os.getenv("GHOST_URL", "http://172.19.0.3:2368")
GHOST_KEY = os.getenv("GHOST_ADMIN_API_KEY", "") or os.getenv("GHOST_CONTENT_API_KEY", "")


async def _openrouter_chat(model: str, system: str, user: str, max_tokens: int = 1500, temperature: float = 0.5) -> str:
    """Call OpenRouter with a free model."""
    if not OPENROUTER_KEY:
        return ""

    try:
        async with httpx.AsyncClient(timeout=90) as c:
            r = await c.post(
                OPENROUTER_URL,
                headers={
                    "Authorization": f"Bearer {OPENROUTER_KEY}",
                    "Content-Type": "application/json",
                    "HTTP-Referer": "https://rugmunch.io",
                    "X-Title": "RugCharts Daily Intel",
                },
                json={
                    "model": model,
                    "messages": [
                        {"role": "system", "content": system},
                        {"role": "user", "content": user},
                    ],
                    "temperature": temperature,
                    "max_tokens": max_tokens,
                },
            )
            if r.status_code == 200:
                return r.json()["choices"][0]["message"]["content"]
            else:
                logger.warning(f"OpenRouter {model}: {r.status_code} {r.text[:200]}")
                return ""
    except Exception as e:
        logger.warning(f"OpenRouter error: {e}")
        return ""


async def _gather_all_data() -> dict:
    """Gather comprehensive data from ALL DataBus sources."""
    data = {
        "market": {},
        "fear_greed": {},
        "news": {},
        "ct": {},
        "social": {},
        "prediction_markets": {},
    }

    # Market data
    try:
        from app.databus.news_provider import get_market_brief

        data["market"] = await get_market_brief()
    except Exception:
        pass

    # News intel
    try:
        from app.databus.news_intel import aggregate_all_news

        data["news"] = await aggregate_all_news(limit=20)
    except Exception:
        pass

    # CT Rundown
    try:
        from app.databus.x_intel import fetch_ct_rundown

        data["ct"] = await fetch_ct_rundown(limit=15)
    except Exception:
        pass

    # Social metrics
    try:
        from app.databus.social_intel import get_social_metrics

        data["social"] = await get_social_metrics()
    except Exception:
        pass

    # Fear & Greed
    try:
        from app.databus.news_provider import get_fear_greed

        data["fear_greed"] = await get_fear_greed()
    except Exception:
        pass

    # Prediction markets
    try:
        from app.databus.news_provider import get_prediction_markets

        data["prediction_markets"] = await get_prediction_markets(limit=5)
    except Exception:
        pass

    return data


def _build_research_context(data: dict) -> str:
    """Build comprehensive context for the research model."""
    parts = []

    # Market snapshot
    market = data.get("market", {})
    if market.get("brief"):
        parts.append(f"## MARKET SNAPSHOT\n{market['brief']}")

    # Fear & Greed
    fg = data.get("fear_greed", {})
    if fg.get("value"):
        parts.append(f"## FEAR & GREED INDEX\n{fg['value']}/100 - {fg.get('classification', 'Neutral')}")

    # News headlines
    news = data.get("news", {})
    articles = news.get("articles", [])
    if articles:
        headlines = "\n".join(
            f"- [{a.get('sentiment', {}).get('sentiment', '➖')}] {a.get('title', '')}" for a in articles[:15]  # noqa: RUF001
        )
        parts.append(f"## TOP HEADLINES\n{headlines}")

    # CT Pulse
    ct = data.get("ct", {})
    rundown = ct.get("rundown", [])
    if rundown:
        ct_pulse = "\n".join(f"- @{s.get('author_handle', '?')}: {s.get('text', '')[:150]}" for s in rundown[:10])
        parts.append(f"## CRYPTO TWITTER PULSE\n{ct_pulse}")

    # Social metrics
    social = data.get("social", {})
    if social.get("trending_topics"):
        topics = social["trending_topics"]
        parts.append(f"## TRENDING TOPICS\n{', '.join(list(topics.keys())[:10])}")

    # Prediction markets
    pm = data.get("prediction_markets", {})
    pmarkets = pm.get("markets", [])
    if pmarkets:
        pm_str = "\n".join(f"- {m.get('title', '')[:80]}: ${m.get('volume', 0):,.0f} vol" for m in pmarkets[:3])
        parts.append(f"## PREDICTION MARKETS\n{pm_str}")

    return "\n\n".join(parts)


WRITING_STANDARDS = """You are a senior financial writer for RugCharts Daily Intelligence.

WRITING STANDARDS:
- Human, conversational tone. Like a sharp newsletter, not a robot.
- No AI-isms: never use "delve", "tapestry", "landscape", "robust", "moreover", "furthermore"
- Lead with the most important story. Hook the reader.
- Be specific: use numbers, names, percentages. No vague statements.
- Include market sentiment, social mood, and what traders are actually talking about
- One section on MEMES/CULTURE - what's trending on CT
- One section on RISK RADAR - scams, hacks, regulatory threats to watch
- End with BOTTOM LINE - actionable takeaway in 2 sentences

FORMAT EXACTLY LIKE THIS:

# RUGCHARTS DAILY INTELLIGENCE
## {Date}

### MARKET SNAPSHOT
{2-3 sentences on overall market}

### TOP STORIES
{3-5 bullet points of most important news with brief context}

### SENTIMENT CHECK
{Market mood: fear/greed, social sentiment, what CT is feeling}

### MEMES & CULTURE
{What's trending on CT, notable memes, cultural moments}

### RISK RADAR
{Scams, hacks, regulatory actions, things to avoid today}

### BOTTOM LINE
{1-2 sentence actionable takeaway}

---
Published by RugCharts Daily Intelligence
Subscribe: https://rugmunch.io/news"""


async def generate_daily_intel(publish: bool = False, **kw) -> dict | None:
    """Generate the complete Daily Intelligence Briefing with quality review.

    Pipeline: Gather → Research → Write → Review → Fix → Publish
    All AI calls through model_registry (free models only).
    Ghost is canonical. X/Telegram are syndication.

    Args:
        publish: If True, publish to Ghost (primary) + X/Telegram (syndication)
    """
    from app.databus.model_registry import ai_call, review_content

    # ── PHASE 0: Gather all data ──
    logger.info("Daily Intel: gathering data...")
    data = await _gather_all_data()
    context = _build_research_context(data)

    if len(context) < 100:
        return {"error": "Insufficient data gathered"}

    # ── PHASE 1: Research ──
    logger.info("Daily Intel: research phase (free model)...")
    research_notes = await ai_call(
        "research",
        "You are a senior crypto research analyst. Analyze data and produce structured research notes with specific numbers and names.",
        f"Analyze today's crypto market data. Identify top 3 stories, sentiment drivers, risks, cultural trends, and on-chain signals:\n\n{context}",
        max_tokens=1200,
        temperature=0.3,
    )
    if not research_notes:
        research_notes = "Research phase: raw data analysis (no AI available).\n\n" + context[:2000]

    # ── PHASE 2: Writing ──
    logger.info("Daily Intel: writing phase (free model)...")
    now = datetime.now(UTC)
    date_str = now.strftime("%A, %B %d, %Y")

    writing_prompt = f"""Write today's RugCharts Daily Intelligence.

Today: {date_str}

Research notes:
{research_notes}

Raw context:
{context[:2500]}

FORMAT:
# RUGCHARTS DAILY INTELLIGENCE
## {date_str}

### MARKET SNAPSHOT
2-3 sentences on overall market direction and key drivers.

### TOP STORIES
3-5 bullet points with specific numbers, names, and context.

### SENTIMENT CHECK
Market mood, social sentiment, fear/greed, what CT is saying.

### MEMES & CULTURE
What's trending on CT. Notable narratives. Cultural moments.

### RISK RADAR
Scams, hacks, regulatory actions. What to avoid today.

### BOTTOM LINE
1-2 sentence actionable takeaway.
"""

    final_report = await ai_call("writing", WRITING_STANDARDS, writing_prompt, max_tokens=2000, temperature=0.7)

    if not final_report or len(final_report) < 200:
        headlines = data.get("news", {}).get("articles", [])
        final_report = f"""# RUGCHARTS DAILY INTELLIGENCE
## {date_str}

### MARKET SNAPSHOT
{data.get("market", {}).get("brief", "Market data unavailable")}

### TOP STORIES
{chr(10).join("- " + a.get("title", "") for a in headlines[:5])}

### SENTIMENT CHECK
Fear & Greed: {data.get("fear_greed", {}).get("value", "?")}/100

### BOTTOM LINE
Stay sharp. Data-driven decisions only."""

    # ── PHASE 3: Review ──
    logger.info("Daily Intel: quality review...")
    review = await review_content(final_report, "daily_briefing")

    if not review["pass"] and review.get("fixed_version"):
        logger.info(f"Daily Intel: auto-fixed (score {review['score']}/100)")
        final_report = review["fixed_version"]
    else:
        logger.info(f"Daily Intel: passed review ({review['score']}/100)")

    report_data = {
        "report": final_report,
        "date": date_str,
        "research_model": "free_openrouter",
        "writing_model": "free_openrouter",
        "review_score": review["score"],
        "review_issues": review.get("issues", []),
        "data_sources": sum(1 for v in data.values() if v),
        "generated_at": datetime.now(UTC).isoformat(),
        "published": False,
        "source": "daily_intel_briefing",
    }

    # ── PHASE 4: Publish (Ghost first, then syndicate) ──
    if publish:
        pub_results = await _publish_briefing(final_report, date_str)
        report_data["published"] = True
        report_data["publish_results"] = pub_results

    return report_data


async def _publish_briefing(report: str, date_str: str) -> dict:
    """Publish the briefing to all channels."""
    results = {}

    # ── X/Twitter via xurl ──
    x_result = await _publish_to_x(report, date_str)
    results["x"] = x_result

    # ── Ghost CMS ──
    ghost_result = await _publish_to_ghost(report, date_str)
    results["ghost"] = ghost_result

    # ── Telegram (via send_message or bot) ──
    tg_result = await _publish_to_telegram(report, date_str)
    results["telegram"] = tg_result

    return results


async def _publish_to_x(report: str, date_str: str) -> dict:
    """Publish briefing summary to X @CryptoRugMunch via xurl."""
    # Extract top story + TLDR for tweet thread
    lines = report.split("\n")
    headline = ""
    tldr = ""

    for line in lines:
        if line.startswith("### MARKET SNAPSHOT") or line.startswith("##"):
            continue
        if not headline and len(line.strip()) > 20:
            headline = line.strip().lstrip("#- ")[:240]
        if "BOTTOM LINE" in line:
            # Grab the next line
            idx = lines.index(line)
            if idx + 1 < len(lines):
                tldr = lines[idx + 1].strip().lstrip("- ")[:240]

    if not headline:
        headline = f"RugCharts Daily Intelligence - {date_str}"

    tweet_text = f"📊 {headline}\n\n{tldr}\n\nFull report: https://rugmunch.io/news"

    try:
        result = subprocess.run(
            ["xurl", "post", tweet_text, "--auth", "oauth2"],
            capture_output=True,
            text=True,
            timeout=20,
        )
        if result.returncode == 0:
            return {"status": "posted", "platform": "x", "length": len(tweet_text)}
        else:
            return {"status": "failed", "platform": "x", "error": result.stderr[:200]}
    except Exception as e:
        return {"status": "error", "platform": "x", "error": str(e)[:200]}


async def _publish_to_ghost(report: str, date_str: str) -> dict:
    """Publish briefing to Ghost CMS under 'daily' tag."""
    if not GHOST_URL or not GHOST_KEY:
        return {"status": "skipped", "reason": "Ghost not configured"}

    try:
        # Extract title from report
        report.split("\n")
        title = f"Daily Intelligence - {date_str}"

        # Convert markdown to Ghost HTML
        html = _markdown_to_html(report)

        async with httpx.AsyncClient(timeout=20) as c:
            r = await c.post(
                f"{GHOST_URL}/ghost/api/admin/posts/",
                headers={
                    "Authorization": f"Ghost {GHOST_KEY}",
                    "Content-Type": "application/json",
                    "Accept-Version": "v5.0",
                },
                json={
                    "posts": [
                        {
                            "title": title,
                            "html": html,
                            "status": "published",
                            "tags": ["daily", "intelligence", "briefing"],
                            "feature_image": "",
                        }
                    ]
                },
            )
            if r.status_code in (200, 201):
                return {"status": "published", "platform": "ghost"}
            else:
                return {"status": "failed", "platform": "ghost", "error": r.text[:200]}
    except Exception as e:
        return {"status": "error", "platform": "ghost", "error": str(e)[:200]}


async def _publish_to_telegram(report: str, date_str: str) -> dict:
    """Send briefing to Telegram channel."""
    bot_token = os.getenv("TELEGRAM_BOT_TOKEN", "")
    channel = os.getenv("CHANNEL_NEWS", "") or os.getenv("CHANNEL_ALERTS", "")

    if not bot_token or not channel:
        return {"status": "skipped", "reason": "Telegram not configured"}

    # Create a shorter version for Telegram
    lines = report.split("\n")
    tg_text = f"📊 *RugCharts Daily Intelligence*\n{date_str}\n\n"

    # Extract key sections
    for i, line in enumerate(lines):
        if line.startswith("### "):
            tg_text += f"\n*{line.strip('# ')}*\n"
        elif line.startswith("- ") and len(tg_text) < 3500:
            tg_text += f"{line}\n"
        elif "BOTTOM LINE" in line and i + 1 < len(lines):
            tg_text += f"\n💡 *Bottom Line:* {next_line}\n"  # noqa: F821  -- pre-existing bug, see fix(f821) tracking issue
            break

    tg_text += "\n🔗 Full report: https://rugmunch.io/news"

    try:
        async with httpx.AsyncClient(timeout=15) as c:
            r = await c.post(
                f"https://api.telegram.org/bot{bot_token}/sendMessage",
                json={
                    "chat_id": channel,
                    "text": tg_text[:4000],
                    "parse_mode": "Markdown",
                    "disable_web_page_preview": False,
                },
            )
            if r.status_code == 200:
                return {"status": "sent", "platform": "telegram"}
            else:
                return {"status": "failed", "platform": "telegram", "error": r.text[:200]}
    except Exception as e:
        return {"status": "error", "platform": "telegram", "error": str(e)[:200]}


def _markdown_to_html(md: str) -> str:
    """Simple markdown to HTML conversion for Ghost."""
    html = md
    html = re.sub(r"^# (.+)$", r"<h1>\1</h1>", html, flags=re.MULTILINE)
    html = re.sub(r"^## (.+)$", r"<h2>\1</h2>", html, flags=re.MULTILINE)
    html = re.sub(r"^### (.+)$", r"<h3>\1</h3>", html, flags=re.MULTILINE)
    html = re.sub(r"^- (.+)$", r"<li>\1</li>", html, flags=re.MULTILINE)
    html = re.sub(r"\*\*(.+?)\*\*", r"<strong>\1</strong>", html)
    html = html.replace("\n\n", "</p><p>").replace("\n", "<br>")
    html = f"<p>{html}</p>"
    html = html.replace("<p><h", "<h").replace("</h2></p>", "</h2>").replace("</h1></p>", "</h1>")
    return html
