import urllib.request
import urllib.parse
import json
import logging
from typing import Optional
from mcp.server.fastmcp import FastMCP

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("anitabi-mcpserver")

# Initialize FastMCP server
mcp = FastMCP("anitabi-mcpserver")

USER_AGENT = "thinktraveller/anitabi-mcpserver (https://github.com/thinktraveller/Anitabi_MCPserver)"

def _safe_execute(func, *args, **kwargs) -> str:
    """Safe execution wrapper to catch exceptions and ensure JSON serialization."""
    try:
        result = func(*args, **kwargs)
        return json.dumps(result, ensure_ascii=False, indent=2)
    except urllib.error.HTTPError as e:
        error_msg = {"error": f"HTTP Error: {e.code} - {e.reason}"}
        return json.dumps(error_msg, ensure_ascii=False)
    except Exception as e:
        error_msg = {"error": str(e)}
        return json.dumps(error_msg, ensure_ascii=False)

def _search_bangumi(keyword: str) -> dict:
    url = f"https://api.bgm.tv/search/subject/{urllib.parse.quote(keyword)}?type=2"
    req = urllib.request.Request(url, headers={'User-Agent': USER_AGENT})
    with urllib.request.urlopen(req) as response:
        return json.loads(response.read().decode('utf-8'))

def _get_anitabi_lite(subject_id: int) -> dict:
    url = f"https://api.anitabi.cn/bangumi/{subject_id}/lite"
    req = urllib.request.Request(url, headers={'User-Agent': USER_AGENT})
    with urllib.request.urlopen(req) as response:
        return json.loads(response.read().decode('utf-8'))

def _get_anitabi_detail(subject_id: int) -> list:
    url = f"https://api.anitabi.cn/bangumi/{subject_id}/points/detail?haveImage=true"
    req = urllib.request.Request(url, headers={'User-Agent': USER_AGENT})
    with urllib.request.urlopen(req) as response:
        return json.loads(response.read().decode('utf-8'))

@mcp.tool()
def search_bangumi(keyword: str) -> str:
    """
    Search for a bangumi (anime) by Chinese/Japanese/English name to get its Bangumi ID, which is required for querying seichi junrei locations.
    
    Args:
        keyword: The name of the anime to search for.
    
    Returns:
        JSON string containing search results with Bangumi IDs.
    """
    return _safe_execute(_search_bangumi, keyword)

@mcp.tool()
def get_anime_lite_info(subject_id: int) -> str:
    """
    Get the lite info of seichi junrei (anime pilgrimage) locations for a specific anime using its Bangumi ID.
    
    Args:
        subject_id: The Bangumi ID of the anime.
        
    Returns:
        JSON string containing the lite info, including `litePoints` which are the top 10 iconic locations.
    """
    return _safe_execute(_get_anitabi_lite, subject_id)

@mcp.tool()
def get_anime_detail_points(subject_id: int) -> str:
    """
    Get the detailed seichi junrei (anime pilgrimage) locations for a specific anime using its Bangumi ID.
    
    Args:
        subject_id: The Bangumi ID of the anime.
        
    Returns:
        JSON string containing a list of detailed location points.
    """
    return _safe_execute(_get_anitabi_detail, subject_id)

def main():
    """Main entry point for the MCP server."""
    mcp.run()

if __name__ == "__main__":
    main()
