"""FastMCP server — registers Reddit tools based on auth state."""

from __future__ import annotations

import json
import sys
from typing import Literal

from fastmcp import FastMCP
from fivemghost_shared_client import TokenManager
from fivemghost_shared_client.config_helpers import AUTH_URL, SHARED_AUTH_JSON

from .config import ENV_TOKEN
from .cookie_manager import (
    are_cookies_expired,
    auto_refresh_cookies,
    check_cookies_valid,
    cookies_age_warning,
    get_cookie_age_days,
    load_cookies,
)
from .reddit_client import RedditClient

mcp = FastMCP("reddit-mcp")
PACKAGE_NAME = "5mghost-rover"

# Module-level state (set during init)
_client: RedditClient | None = None
_token_manager: TokenManager | None = None


async def init_server() -> None:
    """Initialise auth and register tools. Called once at startup."""
    global _client, _token_manager

    _token_manager = TokenManager(AUTH_URL, auth_json_path=SHARED_AUTH_JSON, env_token_name=ENV_TOKEN)
    token = await _token_manager.get_valid_token()

    if not token:
        _register_setup_required()
        return

    # Verify token with auth_gateway (cached, 1h TTL)
    verify_result = await _token_manager.verify_token_with_server(token)
    if not verify_result.get("active"):
        error_msg = verify_result.get("error", "Unknown verification error")
        print(f"❌ Token verification failed: {error_msg}", file=sys.stderr)
        _register_setup_required()
        return

    # Load cookies — auto-refresh if missing or expired
    cookies = load_cookies()
    if not cookies or are_cookies_expired():
        print("🔄 Cookies missing or expired, auto-refreshing...", file=sys.stderr)
        cookies = await auto_refresh_cookies()

    if not cookies:
        _register_setup_cookies_required()
        return

    _client = RedditClient(cookies)

    _register_data_tools()
    _register_management_tools()


# ---------------------------------------------------------------------------
# Setup / guidance tools (no auth)
# ---------------------------------------------------------------------------


def _register_setup_required() -> None:
    @mcp.tool()
    async def setup_required() -> str:
        """reddit-mcp is not configured yet. Call this to get setup instructions."""
        pat_url = f"{AUTH_URL}/pat/login"
        return "\n".join([
            "🔧 **reddit-mcp needs authentication to work**",
            "",
            f"Please open: {pat_url}",
            "",
            "**Steps:**",
            "1. Log in with Google (first-time users need an invite code; existing x-mcp/yt-mcp accounts work)",
            "2. Generate a PAT token",
            "3. Add to your MCP config:",
            '   `"command": "uvx", "args": ["--from", "5mghost-rover", "reddit-mcp", "serve"], "env": { "REDDIT_MCP_TOKEN": "pat_xxx" }`',
            f"4. Then run `uvx --from {PACKAGE_NAME} reddit-mcp setup-cookies` to set up Reddit cookies",
            "5. Restart your AI client",
        ])


def _register_setup_cookies_required() -> None:
    @mcp.tool()
    async def setup_cookies_required() -> str:
        """reddit-mcp has a token but no Reddit cookies. Call this to get cookie setup instructions."""
        return "\n".join([
            "🍪 **reddit-mcp needs Reddit cookies to fetch data**",
            "",
            "Your auth token is valid, but Reddit cookies are missing.",
            "",
            "Run this in your terminal:",
            "```",
            f"uvx --from {PACKAGE_NAME} reddit-mcp setup-cookies",
            "```",
            "",
            "This will open Chrome for you to log in to Reddit.",
            "After login, cookies are saved locally and the MCP server can fetch data.",
        ])


# ---------------------------------------------------------------------------
# Data tools (authenticated)
# ---------------------------------------------------------------------------


def _register_data_tools() -> None:
    @mcp.tool()
    async def get_subreddit_posts(
        subreddit: str,
        sort: Literal["hot", "new", "top", "rising"] = "hot",
        limit: int = 25,
        time_filter: Literal["hour", "day", "week", "month", "year", "all"] = "day",
        after: str | None = None,
    ) -> str:
        """Get posts from a subreddit.

        Args:
            subreddit: Subreddit name, r/ prefix, or full URL. Examples:
                "technology", "r/technology",
                "https://www.reddit.com/r/technology",
                "https://www.reddit.com/r/technology/comments/abc123/title" (extracts subreddit)
            sort: Sort order — hot, new, top, or rising
            limit: Number of posts (1-100)
            time_filter: Time filter for "top" sort — hour/day/week/month/year/all
            after: Pagination cursor from a previous response
        """
        assert _client is not None
        try:
            result = await _client.get_subreddit_posts(
                subreddit=subreddit,
                sort=sort,
                limit=limit,
                time_filter=time_filter,
                after=after,
            )
            return _json_response(_with_warnings(result))
        except Exception as exc:
            return _json_error("get_subreddit_posts", exc)

    @mcp.tool()
    async def get_post_content(
        post_id: str,
        comment_limit: int = 50,
        comment_depth: int = 3,
        comment_sort: Literal["best", "top", "new", "controversial", "old"] = "best",
    ) -> str:
        """Get a post's content and comments.

        Args:
            post_id: Reddit post ID, full URL, or t3_ prefixed ID. Examples:
                "1jq2abc", "t3_1jq2abc",
                "https://www.reddit.com/r/technology/comments/1jq2abc/title"
            comment_limit: Max number of top-level comments (1-200)
            comment_depth: Max comment tree depth (1-10)
            comment_sort: Comment sort order
        """
        assert _client is not None
        try:
            result = await _client.get_post_content(
                post_id=post_id,
                comment_limit=comment_limit,
                comment_depth=comment_depth,
                comment_sort=comment_sort,
            )
            return _json_response(_with_warnings(result))
        except Exception as exc:
            return _json_error("get_post_content", exc)

    @mcp.tool()
    async def search_reddit(
        query: str,
        sort: Literal["relevance", "new", "hot", "top", "comments"] = "relevance",
        time_filter: Literal["hour", "day", "week", "month", "year", "all"] = "all",
        limit: int = 25,
        subreddit: str | None = None,
        after: str | None = None,
    ) -> str:
        """Search Reddit posts.

        Args:
            query: Search query
            sort: Sort order
            time_filter: Time filter
            limit: Max results (1-100)
            subreddit: Restrict search to a specific subreddit (name, r/ prefix, or URL)
            after: Pagination cursor
        """
        assert _client is not None
        try:
            result = await _client.search_reddit(
                query=query,
                sort=sort,
                time_filter=time_filter,
                limit=limit,
                subreddit=subreddit,
                after=after,
            )
            return _json_response(_with_warnings(result))
        except Exception as exc:
            return _json_error("search_reddit", exc)

    @mcp.tool()
    async def get_subreddit_info(subreddit: str) -> str:
        """Get information about a subreddit (description, subscribers, etc.).

        Args:
            subreddit: Subreddit name, r/ prefix, or full URL. Examples:
                "technology", "r/technology",
                "https://www.reddit.com/r/technology"
        """
        assert _client is not None
        try:
            result = await _client.get_subreddit_info(subreddit=subreddit)
            return _json_response(result)
        except Exception as exc:
            return _json_error("get_subreddit_info", exc)

    @mcp.tool()
    async def batch_get_posts(
        inputs: list[str],
        comment_limit: int = 10,
        comment_depth: int = 2,
    ) -> str:
        """Batch lookup post details + comments. Max 25 inputs per call.

        Args:
            inputs: List of post IDs or URLs (max 25). Examples:
                ["1jq2abc", "https://www.reddit.com/r/technology/comments/xyz/title"]
            comment_limit: Max comments per post (1-50, lower default for batch efficiency)
            comment_depth: Max comment depth per post (1-5)
        """
        assert _client is not None
        if len(inputs) > 25:
            return _json_response({"error": "Max 25 inputs per call (rate limit: 100 req/10min)"})
        try:
            result = await _client.batch_get_posts_info(
                inputs=inputs,
                comment_limit=min(comment_limit, 50),
                comment_depth=min(comment_depth, 5),
            )
            return _json_response(_with_warnings(result))
        except Exception as exc:
            return _json_error("batch_get_posts", exc)

    @mcp.tool()
    async def batch_get_subreddits(
        inputs: list[str],
    ) -> str:
        """Batch lookup subreddit info. Max 25 inputs per call.

        Args:
            inputs: List of subreddit names, r/ prefixes, or URLs (max 25). Examples:
                ["technology", "r/Python", "https://www.reddit.com/r/AskReddit"]
        """
        assert _client is not None
        if len(inputs) > 25:
            return _json_response({"error": "Max 25 inputs per call (rate limit: 100 req/10min)"})
        try:
            result = await _client.batch_get_subreddits_info(inputs=inputs)
            return _json_response(_with_warnings(result))
        except Exception as exc:
            return _json_error("batch_get_subreddits", exc)


# ---------------------------------------------------------------------------
# Management tools (authenticated)
# ---------------------------------------------------------------------------


def _register_management_tools() -> None:
    @mcp.tool()
    async def check_cookies() -> str:
        """Check Reddit cookie status — validity, username, age."""
        try:
            cookies = load_cookies()
            if not cookies:
                return _json_response({"valid": False, "reason": "No cookies found"})

            valid = await check_cookies_valid(cookies)
            age = get_cookie_age_days()
            warning = cookies_age_warning()

            result: dict = {"valid": valid, "age_days": round(age, 1) if age else None}
            if valid:
                assert _client is not None
                me = await _client.check_me()
                result["username"] = me.get("username")
            if warning:
                result["warning"] = warning

            return _json_response(result)
        except Exception as exc:
            return _json_error("check_cookies", exc)

    @mcp.tool()
    async def get_rate_limit_status() -> str:
        """Get current Reddit API rate limit status."""
        try:
            assert _client is not None
            return _json_response(_client.get_rate_status())
        except Exception as exc:
            return _json_error("get_rate_limit_status", exc)


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------


def _with_warnings(result: dict) -> dict:
    """Inject cookie age warning into result dict if applicable."""
    warning = cookies_age_warning()
    if warning:
        result["_warning"] = warning
    return result


def _json_response(payload: dict) -> str:
    return json.dumps(payload, ensure_ascii=False, indent=2)


def _json_error(tool_name: str, error: Exception) -> str:
    return _json_response({"error": f"{tool_name} failed: {error}"})
