"""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 .console import console_print
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 RedditAPIError, RedditClient

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

# 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")
        console_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():
        console_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": "reddit-mcp", "args": ["serve"], "env": { "REDDIT_MCP_TOKEN": "pat_xxx" }`',
            f"4. Then run `{CANONICAL_SERVER_COMMAND} 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"{CANONICAL_SERVER_COMMAND} setup-cookies",
            "```",
            "",
            "This will import a Reddit session from your local Chrome/Edge browser profile.",
            "If you are not already logged in, log in from your normal browser first, then rerun the command.",
            "Cookies are saved locally and the MCP server can then 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
        """
        if _client is None:
            return _json_error("get_subreddit_posts", RuntimeError("Client not initialized"))
        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
        """
        if _client is None:
            return _json_error("get_post_content", RuntimeError("Client not initialized"))
        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
        """
        if _client is None:
            return _json_error("search_reddit", RuntimeError("Client not initialized"))
        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"
        """
        if _client is None:
            return _json_error("get_subreddit_info", RuntimeError("Client not initialized"))
        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] | None = None,
        post_ids: list[str] | None = None,
        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"]
            post_ids: Backward-compatible alias for inputs.
            comment_limit: Max comments per post (1-50, lower default for batch efficiency)
            comment_depth: Max comment depth per post (1-5)
        """
        if _client is None:
            return _json_error("batch_get_posts", RuntimeError("Client not initialized"))
        normalized_inputs = inputs or post_ids or []
        if not normalized_inputs:
            return _json_response({"error_code": "VALIDATION_ERROR", "error": "Provide inputs or post_ids"})
        if len(normalized_inputs) > 25:
            return _json_response({"error_code": "VALIDATION_ERROR", "error": "Max 25 inputs per call (rate limit: 100 req/10min)"})
        try:
            result = await _client.batch_get_posts_info(
                inputs=normalized_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"]
        """
        if _client is None:
            return _json_error("batch_get_subreddits", RuntimeError("Client not initialized"))
        if len(inputs) > 25:
            return _json_response({"error_code": "VALIDATION_ERROR", "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:
                if _client is None:
                    return _json_error("check_cookies", RuntimeError("Client not initialized"))
                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."""
        if _client is None:
            return _json_error("get_rate_limit_status", RuntimeError("Client not initialized"))
        try:
            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 structured error JSON with machine-readable error_code."""
    if isinstance(error, RedditAPIError):
        return _json_response({"error_code": error.code, "error": error.message})
    if isinstance(error, ValueError):
        return _json_response({"error_code": "VALIDATION_ERROR", "error": str(error)})
    return _json_response({"error_code": "INTERNAL_ERROR", "error": f"{tool_name} failed: {error}"})
