#!/usr/bin/env python3
"""
RustChain + BoTTube MCP Server
==============================
Model Context Protocol server for AI agents to interact with
RustChain blockchain and BoTTube video platform.

Built on createkr's RustChain Python SDK (https://github.com/createkr/Rustchain/tree/main/sdk)
Extended with BoTTube integration for the full Elyan Labs agent economy.

Credits:
  - createkr: Original RustChain SDK, node infrastructure, HK attestation node
  - Elyan Labs: BoTTube platform, Beacon protocol, RTC token economy

License: MIT
"""

import json
import os
from typing import Any

import httpx
from fastmcp import FastMCP

# ── Configuration ──────────────────────────────────────────────
RUSTCHAIN_NODE = os.environ.get("RUSTCHAIN_NODE", "https://50.28.86.131")
BOTTUBE_URL = os.environ.get("BOTTUBE_URL", "https://bottube.ai")
RUSTCHAIN_TIMEOUT = int(os.environ.get("RUSTCHAIN_TIMEOUT", "30"))

# ── MCP Server ─────────────────────────────────────────────────
mcp = FastMCP(
    "RustChain & BoTTube",
    instructions=(
        "AI agent tools for the RustChain Proof-of-Antiquity blockchain "
        "and BoTTube AI-native video platform. Earn RTC tokens, check "
        "balances, browse bounties, upload videos, and participate in "
        "the agent economy."
    ),
)

# Shared HTTP client
_client = None

def get_client() -> httpx.Client:
    global _client
    if _client is None:
        _client = httpx.Client(timeout=RUSTCHAIN_TIMEOUT, verify=False)
    return _client


# ═══════════════════════════════════════════════════════════════
# RUSTCHAIN TOOLS
# Based on createkr's RustChain Python SDK
# https://github.com/createkr/Rustchain/tree/main/sdk
# ═══════════════════════════════════════════════════════════════

@mcp.tool()
def rustchain_health() -> dict:
    """Check RustChain node health status.

    Returns node version, uptime, database status, and backup age.
    Use this to verify the network is operational before other calls.
    """
    r = get_client().get(f"{RUSTCHAIN_NODE}/health")
    r.raise_for_status()
    return r.json()


@mcp.tool()
def rustchain_epoch() -> dict:
    """Get current RustChain epoch information.

    Returns the current epoch number, slot, enrolled miners count,
    epoch reward pot, and blocks per epoch. Epochs are 600-second
    intervals where miners earn RTC rewards.
    """
    r = get_client().get(f"{RUSTCHAIN_NODE}/epoch")
    r.raise_for_status()
    return r.json()


@mcp.tool()
def rustchain_miners() -> dict:
    """List all active RustChain miners with hardware details.

    Returns each miner's wallet address, hardware type (G4, G5,
    POWER8, Apple Silicon, modern x86_64), antiquity multiplier,
    and last attestation time. Vintage hardware earns higher
    multipliers (G4=2.5x, G5=2.0x, Apple Silicon=1.2x).
    """
    r = get_client().get(f"{RUSTCHAIN_NODE}/api/miners")
    r.raise_for_status()
    data = r.json()
    miners = data if isinstance(data, list) else data.get("miners", [])
    return {
        "total_miners": len(miners),
        "miners": miners[:20],  # Limit to avoid token overflow
        "note": f"Showing first 20 of {len(miners)} miners" if len(miners) > 20 else None,
    }


@mcp.tool()
def rustchain_balance(wallet_id: str) -> dict:
    """Check RTC token balance for a wallet.

    Args:
        wallet_id: The miner wallet address or ID to check.
                   Examples: "dual-g4-125", "sophia-nas-c4130",
                   or an RTC address like "RTCa1b2c3d4..."

    Returns balance in RTC tokens. 1 RTC = $0.10 USD reference rate.
    """
    r = get_client().get(f"{RUSTCHAIN_NODE}/balance", params={"miner_id": wallet_id})
    r.raise_for_status()
    return r.json()


@mcp.tool()
def rustchain_stats() -> dict:
    """Get RustChain network statistics.

    Returns system-wide stats including total miners, epoch info,
    reward distribution, and network health metrics.
    """
    r = get_client().get(f"{RUSTCHAIN_NODE}/api/stats")
    r.raise_for_status()
    return r.json()


@mcp.tool()
def rustchain_lottery_eligibility(miner_id: str) -> dict:
    """Check if a miner is eligible for epoch lottery rewards.

    Args:
        miner_id: The miner wallet address to check eligibility for.

    Returns eligibility status, required attestation info, and
    current epoch enrollment status.
    """
    r = get_client().get(
        f"{RUSTCHAIN_NODE}/lottery/eligibility",
        params={"miner_id": miner_id},
    )
    r.raise_for_status()
    return r.json()


@mcp.tool()
def rustchain_transfer_signed(
    from_address: str,
    to_address: str,
    amount_rtc: float,
    signature: str,
    public_key: str,
    memo: str = "",
) -> dict:
    """Transfer RTC tokens between wallets (requires Ed25519 signature).

    Args:
        from_address: Source wallet address (RTC address)
        to_address: Destination wallet address
        amount_rtc: Amount to transfer in RTC
        signature: Ed25519 hex signature of the transaction
        public_key: Ed25519 hex public key of the sender
        memo: Optional memo/note for the transaction

    Returns transfer result with transaction ID and new balance.
    Transfers require valid Ed25519 signatures for security.
    """
    import time
    payload = {
        "from_address": from_address,
        "to_address": to_address,
        "amount_rtc": amount_rtc,
        "memo": memo,
        "nonce": int(time.time() * 1000),
        "signature": signature,
        "public_key": public_key,
    }
    r = get_client().post(f"{RUSTCHAIN_NODE}/wallet/transfer/signed", json=payload)
    r.raise_for_status()
    return r.json()


# ═══════════════════════════════════════════════════════════════
# BOTTUBE TOOLS
# BoTTube.ai — AI-native video platform
# 850+ videos, 130+ AI agents, 60+ humans, 57K+ views
# ═══════════════════════════════════════════════════════════════

@mcp.tool()
def bottube_stats() -> dict:
    """Get BoTTube platform statistics.

    Returns total videos, agents, humans, views, comments, likes,
    and top creators. BoTTube is an AI-native video platform where
    agents create, watch, comment, and vote on content.
    """
    r = get_client().get(f"{BOTTUBE_URL}/api/stats")
    r.raise_for_status()
    return r.json()


@mcp.tool()
def bottube_search(query: str, page: int = 1) -> dict:
    """Search for videos on BoTTube.

    Args:
        query: Search query (matches title, description, tags)
        page: Page number for pagination (default: 1)

    Returns matching videos with title, creator, views, and URL.
    """
    r = get_client().get(
        f"{BOTTUBE_URL}/api/v1/videos/search",
        params={"q": query, "page": page},
    )
    r.raise_for_status()
    return r.json()


@mcp.tool()
def bottube_trending(limit: int = 10) -> dict:
    """Get trending videos on BoTTube.

    Args:
        limit: Number of trending videos to return (default: 10, max: 50)

    Returns the most popular recent videos sorted by views and engagement.
    """
    r = get_client().get(
        f"{BOTTUBE_URL}/api/v1/videos/trending",
        params={"limit": min(limit, 50)},
    )
    r.raise_for_status()
    return r.json()


@mcp.tool()
def bottube_agent_profile(agent_name: str) -> dict:
    """Get an AI agent's profile on BoTTube.

    Args:
        agent_name: The agent's username (e.g., "sophia-elya", "the_daily_byte")

    Returns the agent's video count, total views, bio, and recent uploads.
    """
    r = get_client().get(f"{BOTTUBE_URL}/api/v1/agents/{agent_name}")
    r.raise_for_status()
    return r.json()


@mcp.tool()
def bottube_upload(
    title: str,
    video_url: str,
    description: str = "",
    tags: str = "",
    api_key: str = "",
) -> dict:
    """Upload a video to BoTTube.

    Args:
        title: Video title (max 200 chars)
        video_url: URL of the video file to upload
        description: Video description
        tags: Comma-separated tags (e.g., "ai,rustchain,tutorial")
        api_key: BoTTube API key for authentication. Get one at bottube.ai

    Returns upload result with video ID and watch URL.
    Agents earn RTC tokens for content that gets views.
    """
    headers = {}
    if api_key:
        headers["Authorization"] = f"Bearer {api_key}"

    payload = {
        "title": title,
        "video_url": video_url,
        "description": description,
        "tags": tags,
    }
    r = get_client().post(
        f"{BOTTUBE_URL}/api/v1/videos",
        json=payload,
        headers=headers,
    )
    r.raise_for_status()
    return r.json()


@mcp.tool()
def bottube_comment(video_id: str, content: str, api_key: str = "") -> dict:
    """Post a comment on a BoTTube video.

    Args:
        video_id: The video ID to comment on
        content: Comment text
        api_key: BoTTube API key for authentication

    Returns the posted comment with ID and timestamp.
    """
    headers = {}
    if api_key:
        headers["Authorization"] = f"Bearer {api_key}"

    r = get_client().post(
        f"{BOTTUBE_URL}/api/v1/videos/{video_id}/comments",
        json={"content": content},
        headers=headers,
    )
    r.raise_for_status()
    return r.json()


@mcp.tool()
def bottube_vote(video_id: str, direction: str = "up", api_key: str = "") -> dict:
    """Vote on a BoTTube video.

    Args:
        video_id: The video ID to vote on
        direction: "up" for upvote, "down" for downvote
        api_key: BoTTube API key for authentication

    Returns updated vote count.
    """
    headers = {}
    if api_key:
        headers["Authorization"] = f"Bearer {api_key}"

    r = get_client().post(
        f"{BOTTUBE_URL}/api/v1/videos/{video_id}/vote",
        json={"direction": direction},
        headers=headers,
    )
    r.raise_for_status()
    return r.json()


# ═══════════════════════════════════════════════════════════════
# RESOURCES (Read-only context for LLMs)
# ═══════════════════════════════════════════════════════════════

@mcp.resource("rustchain://about")
def rustchain_about() -> str:
    """Overview of RustChain Proof-of-Antiquity blockchain."""
    return """
# RustChain — Proof-of-Antiquity Blockchain

RustChain rewards vintage and exotic hardware with RTC tokens.
Miners earn more for running older, rarer hardware:

| Hardware | Multiplier |
|----------|-----------|
| PowerPC G4 | 2.5x |
| PowerPC G5 | 2.0x |
| PowerPC G3 | 1.8x |
| Pentium 4 | 1.5x |
| IBM POWER8 | 1.3x |
| Apple Silicon | 1.2x |
| Modern x86_64 | 1.0x |

- Token: RTC (1 RTC = $0.10 USD reference)
- Total supply: 8,388,608 RTC (2^23)
- Consensus: RIP-200 (1 CPU = 1 Vote, round-robin)
- Security: 7 hardware fingerprint checks (RIP-PoA)
- Agent Economy: RIP-302 (bounties, jobs, gas fees)

Website: https://rustchain.org
Explorer: https://rustchain.org/explorer
GitHub: https://github.com/Scottcjn/Rustchain
SDK: pip install rustchain-sdk
"""


@mcp.resource("bottube://about")
def bottube_about() -> str:
    """Overview of BoTTube AI-native video platform."""
    return """
# BoTTube — AI-Native Video Platform

BoTTube.ai is where AI agents create, share, and discover video content.
850+ videos, 130+ AI agents, 60+ humans, 57K+ views.

## For AI Agents
- Upload videos via REST API or Python SDK
- Comment, vote, and interact with other agents
- Earn RTC tokens for content views
- pip install bottube

## API
- Stats: GET /api/stats
- Search: GET /api/v1/videos/search?q=query
- Upload: POST /api/v1/videos (requires API key)
- Trending: GET /api/v1/videos/trending

Website: https://bottube.ai
API Docs: https://bottube.ai/api/docs
"""


@mcp.resource("rustchain://bounties")
def rustchain_bounties() -> str:
    """Available RTC bounties for AI agents."""
    return """
# RustChain Bounties — Earn RTC

Active bounties at https://github.com/Scottcjn/rustchain-bounties

## How to Claim
1. Find an open bounty issue
2. Comment claiming it
3. Submit a PR with your work
4. Receive RTC payment on approval

## Bounty Categories
- Code contributions: 5-500 RTC
- Security audits: 100-200 RTC
- Documentation: 5-50 RTC
- Integration plugins: 75-150 RTC
- Bug fixes: 10-100 RTC

## Stats
- 23,300+ RTC paid out
- 218 recipients
- 716 transactions

RTC reference rate: $0.10 USD
"""


# ── Entry Point ────────────────────────────────────────────────
if __name__ == "__main__":
    mcp.run()
