"""O-Score MCP Server: makes the EvE APIs usable by AI agents.

Gives AI assistants (Claude Desktop, Cursor, ChatGPT) direct access to:
  - O-Score      : scores dropshipping products for the EU market (0-100)
  - VAT Check    : validates EU VAT numbers via VIES, plus rates per country
  - Omnibus      : checks the EU lowest-price-in-30-days rule

Works two ways:
  1. DIRECT (the default, no key needed for the free tier)
       https://api.insightoperator.org
  2. VIA RAPIDAPI (for paid plans) by setting RAPIDAPI_KEY

Install in Claude Desktop (claude_desktop_config.json):
{
  "mcpServers": {
    "oscore": {
      "command": "python",
      "args": ["/path/to/oscore-mcp-server.py"]
    }
  }
}
On a paid RapidAPI plan, add:
      "env": {"RAPIDAPI_KEY": "your-key"}

Requires: pip install mcp requests
Source: https://insightoperator.org/mcp/
"""
import json
import os

import requests

try:
    from mcp.server.fastmcp import FastMCP
except ImportError:
    raise SystemExit("Installeer eerst: pip install mcp requests")

RAPIDAPI_HOST = "oscore.p.rapidapi.com"
RAPIDAPI_KEY = os.environ.get("RAPIDAPI_KEY", "")
DIRECT_BASE = os.environ.get("OSCORE_API_BASE", "https://api.insightoperator.org")

if RAPIDAPI_KEY:
    BASE = f"https://{RAPIDAPI_HOST}"
    HEADERS = {"X-RapidAPI-Key": RAPIDAPI_KEY,
               "X-RapidAPI-Host": RAPIDAPI_HOST,
               "Content-Type": "application/json"}
else:
    BASE = DIRECT_BASE.rstrip("/")
    HEADERS = {"Content-Type": "application/json"}

_TIMEOUT = 25

mcp = FastMCP("oscore")


def _call(method: str, path: str, payload: dict | None = None) -> str:
    """One place for every network error, so the agent never gets a bare
    stacktrace back but a readable explanation."""
    url = f"{BASE}{path}"
    try:
        if method == "GET":
            r = requests.get(url, headers=HEADERS, timeout=_TIMEOUT)
        else:
            r = requests.post(url, headers=HEADERS, json=payload or {},
                              timeout=_TIMEOUT)
        if r.status_code == 403:
            return json.dumps({"error": "Access denied. Set RAPIDAPI_KEY or "
                                        "use the direct API."})
        if r.status_code == 429:
            return json.dumps({"error": "Rate limit reached. Wait a moment or "
                                        "move to a higher plan."})
        r.raise_for_status()
        return json.dumps(r.json())
    except requests.Timeout:
        return json.dumps({"error": f"Timed out after {_TIMEOUT}s."})
    except requests.RequestException as exc:
        return json.dumps({"error": f"API unreachable: {exc}"})


# ── O-Score ──
@mcp.tool()
def score_product(name: str, cost_price: float,
                  sell_price: float | None = None,
                  eu_delivery_days: int | None = None,
                  eu_warehouse: bool = False,
                  category: str = "") -> str:
    """Score a dropshipping product for the EU market (0-100 O-Score).
    Combines net margin, EU delivery time, warehouse availability and
    risk flags into one score with a clear verdict."""
    return _call("POST", "/api/v1/score",
                 {"name": name, "cost_price": cost_price,
                  "sell_price": sell_price,
                  "eu_delivery_days": eu_delivery_days,
                  "eu_warehouse": eu_warehouse, "category": category})


@mcp.tool()
def bulk_score(products: list) -> str:
    """Score up to 25 products at once. Each item needs at least
    'name' and 'cost_price'. Returns a ranked list."""
    return _call("POST", "/api/v1/bulk-score", {"products": products})


@mcp.tool()
def trending_niches() -> str:
    """Get trending EU dropshipping niches with average O-Scores."""
    return _call("GET", "/api/v1/niches/trending")


# ── VAT Check ──
@mcp.tool()
def validate_vat(country_code: str, vat_number: str) -> str:
    """Validate an EU VAT number against the official VIES service.
    Use the country code as it appears in VIES (Greece is 'EL', not 'GR').
    Returns validity plus the registered company name and address."""
    return _call("POST", "/api/v2/vat/validate",
                 {"country_code": country_code, "vat_number": vat_number})


@mcp.tool()
def vat_rates(country_code: str = "") -> str:
    """Get EU VAT rates. Without a country code you get all 27 member
    states; with one you get that country's standard and reduced rates."""
    path = f"/api/v2/vat/rates/{country_code}" if country_code \
        else "/api/v2/vat/rates"
    return _call("GET", path)


@mcp.tool()
def omnibus_check(current_price: float, price_history: list,
                  announced_discount_from: float | None = None) -> str:
    """Check compliance with the EU Omnibus directive (2019/2161), which
    requires showing the lowest price of the previous 30 days when
    announcing a discount. price_history is a list of
    {"price": float, "date": "YYYY-MM-DD"} entries."""
    return _call("POST", "/api/v2/omnibus/lowest-price",
                 {"current_price": current_price,
                  "price_history": price_history,
                  "announced_discount_from": announced_discount_from})


@mcp.tool()
def shipping_threshold(avg_order_value: float, margin_pct: float,
                       shipping_cost: float) -> str:
    """Calculate a margin-safe free-shipping threshold that lifts average
    order value without eating the margin."""
    return _call("POST", "/api/v2/shipping/threshold",
                 {"avg_order_value": avg_order_value,
                  "margin_pct": margin_pct,
                  "shipping_cost": shipping_cost})


if __name__ == "__main__":
    mcp.run()
