"""Stobo MCP Server — exposes Stobo API as tools for Claude Desktop."""

from __future__ import annotations

import json
import os

from mcp.server.fastmcp import FastMCP

from stobo.client import StoboAPIError, StoboClient

mcp = FastMCP(
    "Stobo",
    instructions="""Stobo is an AI-powered SEO and AEO (Answer Engine Optimization) audit platform.

CRITICAL ROUTING RULE — READ THIS FIRST:
- DEFAULT: Always use audit_site for any domain, homepage, or generic "audit this" request.
- ONLY use audit_article when the URL is clearly a specific blog post or article (contains /blog/, /post/, /article/, /news/ in the path, or user explicitly says "audit this article/post").
- When in doubt, use audit_site. It is the main entry point.

ROUTING EXAMPLES:
- "audit phantombuster.com" → audit_site ✅ (NOT audit_article)
- "audit https://example.com" → audit_site ✅
- "analyse my website" → audit_site ✅
- "run an audit on example.com" → audit_site ✅
- "check https://example.com/blog/my-post" → audit_article ✅ (specific article URL)
- "audit this article: URL" → audit_article ✅ (user said "article")

TWO LEVELS:
1. audit_site — Website-level: 30 SEO checks + 16 AEO checks + blog scanner. The DEFAULT tool.
2. audit_article — Article-level: 7 SEO + 14 AEO checks on a single blog post/article. Only for specific article URLs.

BLOG SCANNER (part of audit_site):
- audit_site detects blogs and counts articles via sitemap discovery.
- If blog_detection.has_blog is true, proactively suggest next steps:
  - "I found a blog at /blog with ~N articles. Want me to scan freshness or audit a few articles?"
  - Use freshness_audit(blog_url) to scan schema compliance across all articles.
  - Use audit_article(article_url) to deep-dive into specific posts.

TOOLS THAT WORK WITHOUT AUTH: audit_site, audit_article, audit_seo, audit_aeo, freshness_audit
TOOLS THAT NEED API KEY: extract_tone, get_tone, list_tone_profiles, optimize, get_job, export_report, list_audits, get_audit""",
)


def _get_client() -> StoboClient:
    api_key = os.environ.get("STOBO_API_KEY", "")
    base_url = os.environ.get("STOBO_BASE_URL", "https://api.trystobo.com")
    return StoboClient(base_url=base_url, api_key=api_key, user_agent="stobo-mcp/0.1.3")


def _call(fn, *args, **kwargs) -> str:
    """Call a client method and return JSON string, handling errors."""
    try:
        result = fn(*args, **kwargs)
        return json.dumps(result, indent=2, default=str)
    except StoboAPIError as e:
        return json.dumps({"error": e.detail, "status_code": e.status_code})
    except Exception as e:
        return json.dumps({"error": str(e)})


# ── Site Audit (orchestrator) ────────────────────────────────────────


@mcp.tool()
def audit_site(url: str) -> str:
    """Run a full site audit: 30 SEO checks + 16 AEO checks + blog scanner. This is the main entry point for analysing a website. Returns SEO grade, AEO score, blog detection (with sitemap URL and article count), and combined percentage. Results are cached for 24h. If a blog is detected, suggest freshness_audit or audit_article as next steps."""
    client = _get_client()
    return _call(client.audit_site, url)


# ── Article Audit Tools ─────────────────────────────────────────────


@mcp.tool()
def audit_article(
    url: str,
    keyword: str | None = None,
    use_playwright: bool = False,
) -> str:
    """Audit a single blog post or article page (NOT a homepage or domain — use audit_site for that). Runs 7 SEO + 14 AEO checks. Only use when the URL points to a specific article (e.g. /blog/my-post)."""
    client = _get_client()
    return _call(client.audit_article, url, keyword=keyword, use_playwright=use_playwright)


@mcp.tool()
def audit_seo(url: str, keyword: str | None = None) -> str:
    """SEO-only audit on a single article page. Use audit_site for full website SEO. Use audit_article for combined SEO+AEO on an article."""
    client = _get_client()
    return _call(client.audit_seo, url, keyword=keyword)


@mcp.tool()
def audit_aeo(url: str) -> str:
    """AEO-only audit on a single article page. Use audit_site for full website AEO. Use audit_article for combined SEO+AEO on an article."""
    client = _get_client()
    return _call(client.audit_aeo, url)


@mcp.tool()
def get_audit(audit_id: str) -> str:
    """Fetch a previously completed audit by its ID."""
    client = _get_client()
    return _call(client.get_audit, audit_id)


@mcp.tool()
def list_audits(skip: int = 0, limit: int = 20) -> str:
    """List recent audits with pagination."""
    client = _get_client()
    return _call(client.list_audits, skip=skip, limit=limit)


# ── Tone Tools ───────────────────────────────────────────────────────


@mcp.tool()
def extract_tone(
    blog_url: str,
    customer_id: str | None = None,
    max_articles: int = 10,
) -> str:
    """Extract brand voice profile from a blog URL by analyzing its articles."""
    client = _get_client()
    return _call(
        client.extract_tone, blog_url, customer_id=customer_id, max_articles=max_articles
    )


@mcp.tool()
def get_tone(customer_id: str) -> str:
    """Get a stored brand voice/tone profile by customer ID."""
    client = _get_client()
    return _call(client.get_tone, customer_id)


@mcp.tool()
def list_tone_profiles() -> str:
    """List all stored brand voice profiles."""
    client = _get_client()
    return _call(client.list_tone_profiles)


# ── Optimize Tools ───────────────────────────────────────────────────


@mcp.tool()
def optimize(
    url: str,
    customer_id: str | None = None,
    sync: bool = False,
) -> str:
    """Start a full optimization pipeline: audit → tone → rewrite. Returns a job ID to track progress."""
    client = _get_client()
    return _call(client.optimize, url, customer_id=customer_id, sync=sync)


@mcp.tool()
def get_job(job_id: str) -> str:
    """Check the status of an optimization job. Returns progress, status, and results when complete."""
    client = _get_client()
    return _call(client.get_job, job_id)


# ── Freshness Tools ──────────────────────────────────────────────────


@mcp.tool()
def freshness_audit(sitemap_url: str, limit: int = 50) -> str:
    """Audit a sitemap for dateModified schema compliance. Checks content freshness signals."""
    client = _get_client()
    return _call(client.freshness_audit, sitemap_url, limit=limit)


# ── Export Tools ─────────────────────────────────────────────────────


@mcp.tool()
def export_report(
    customer_id: str,
    data_type: str,
) -> str:
    """Generate a markdown export report. data_type can be 'seo', 'aeo', 'tone', or 'full'."""
    client = _get_client()
    return _call(client.export, customer_id, data_type)


def main():
    mcp.run()


if __name__ == "__main__":
    main()
