"""Tracking snippet tools — return framework-specific graph8 installation code."""

from __future__ import annotations

from typing import Any

from mcp.server import FastMCP

from g8_mcp_server.client import G8Client, format_result

SUPPORTED_FRAMEWORKS = {
    "html": "HTML / Vanilla JS",
    "react": "React",
    "nextjs": "Next.js",
    "vue": "Vue",
    "wordpress": "WordPress",
    "webflow": "Webflow",
    "shopify": "Shopify",
}

_PRIVACY_OPTIONS = (
    "Privacy data-attributes (add to the script tag):\n"
    '  data-privacy-dont-send="true"  — Disables cookies and event sending\n'
    '  data-privacy-user-ids="true"   — Disables storing user identifiers\n'
    '  data-privacy-ip-policy="keep"  — IP policy: "keep", "stripLastOctet", or "remove"\n'
    '  data-init-only="true"          — Initializes without sending page event'
)

_VERIFICATION_STEPS = [
    "Open browser DevTools -> Network tab",
    "Look for requests to {tracking_host}/p.js",
    "In Console: window.g8 should be defined",
    "Call g8.track('test_event') — should see a network request",
]


def register(server: FastMCP, client: G8Client) -> None:
    """Register snippet tools on the MCP server."""

    @server.tool()
    async def g8_get_tracking_snippet(
        framework: str,
        repo_id: str | None = None,
    ) -> str:
        """Return the graph8 tracking snippet with framework-specific code.

        IMPORTANT: This is the first step before any other graph8 integration.
        The tracking snippet (p.js) must be loaded on every page before you can
        use g8.identify(), g8.track(), or progressive forms.

        For SSR frameworks (Next.js, WordPress, Shopify): the snippet loads in
        the server-rendered HTML layout, so it's available on every page from
        the first paint.

        For CSR frameworks (React, Vue): the snippet is injected via useEffect
        or onMounted, so it loads after hydration. Use window.g8?.track() to
        safely call tracking methods that depend on the script being ready.

        After installing the snippet, configure tracking:
        1. Add g8.identify(userId, {email, name, ...}) on login/signup
        2. Add g8.track(eventName, {properties}) for key user actions
        3. Then use g8_get_form_template for progressive data collection

        Args:
            framework: Target framework — html, react, nextjs, vue,
                       wordpress, webflow, or shopify
            repo_id: Optional repository ID for repo-specific config
        """
        fw = framework.lower().strip()
        if fw not in SUPPORTED_FRAMEWORKS:
            supported = ", ".join(sorted(SUPPORTED_FRAMEWORKS))
            return format_result({
                "error": f"Unsupported framework '{framework}'",
                "supported_frameworks": supported,
            })

        data = await _fetch_snippet(client, repo_id)
        return format_result(_build_result(fw, data))


async def _fetch_snippet(client: G8Client, repo_id: str | None) -> dict[str, Any]:
    """Fetch snippet config from the API."""
    if repo_id:
        return await client.get(f"/repos/{repo_id}/snippet")
    return await client.get("/snippet")


def _build_result(fw: str, data: dict[str, Any]) -> dict[str, Any]:
    """Assemble the full result dict from API data and a framework template."""
    payload = data.get("data", data)
    write_key = payload.get("write_key", "")
    tracking_host = payload.get("tracking_host", "")

    template_fn = _TEMPLATE_REGISTRY[fw]
    template = template_fn(write_key, tracking_host)

    verification = [
        s.replace("{tracking_host}", tracking_host) for s in _VERIFICATION_STEPS
    ]
    return {
        "write_key": write_key,
        "tracking_host": tracking_host,
        "framework": SUPPORTED_FRAMEWORKS[fw],
        "snippet_code": template["snippet_code"],
        "setup_steps": template["setup_steps"],
        "tracking_methods": template["tracking_methods"],
        "privacy_options": _PRIVACY_OPTIONS,
        "verification": verification,
    }


# ---------------------------------------------------------------------------
# Framework template functions
# ---------------------------------------------------------------------------


def _html_template(write_key: str, tracking_host: str) -> dict:
    """Return HTML/vanilla JS snippet and instructions."""
    snippet = (
        f'<script src="{tracking_host}/p.js"\n'
        f'        data-write-key="{write_key}"\n'
        f'        data-tracking-host="{tracking_host}"\n'
        f"        defer></script>"
    )
    onload = (
        "<script>\n"
        "  window.g8Loaded = function(g8) {\n"
        '    g8.identify("user-id", {email: "john@example.com"})\n'
        "  }\n"
        "</script>\n"
        f'<script src="{tracking_host}/p.js"\n'
        f'        data-write-key="{write_key}"\n'
        f'        data-onload="g8Loaded"\n'
        f"        defer></script>"
    )
    return {
        "snippet_code": f"{snippet}\n\n// Onload pattern:\n{onload}",
        "setup_steps": [
            "Add the script tag inside <head> of your HTML page",
            "Verify in browser console with window.g8",
        ],
        "tracking_methods": _common_tracking_methods(),
    }


def _react_template(write_key: str, tracking_host: str) -> dict:
    """Return React component snippet and instructions."""
    snippet = (
        "// components/G8Analytics.tsx\n"
        "'use client';\n"
        "import { useEffect } from 'react';\n"
        "\n"
        "export function G8Analytics() {\n"
        "  useEffect(() => {\n"
        "    const script = document.createElement('script');\n"
        f"    script.src = '{tracking_host}/p.js';\n"
        "    script.defer = true;\n"
        f"    script.dataset.writeKey = '{write_key}';\n"
        f"    script.dataset.trackingHost = '{tracking_host}';\n"
        "    document.head.appendChild(script);\n"
        "    return () => { document.head.removeChild(script); };\n"
        "  }, []);\n"
        "  return null;\n"
        "}\n"
        "\n"
        "// Usage in App.tsx or layout:\n"
        "// <G8Analytics />\n"
        "\n"
        "// Track events anywhere:\n"
        "// window.g8?.track('button_click', { button: 'signup' });\n"
        "// window.g8?.identify('user-123', { email: 'user@example.com' });"
    )
    return {
        "snippet_code": snippet,
        "setup_steps": [
            "Create components/G8Analytics.tsx with the snippet code",
            "Import and render <G8Analytics /> in your App or layout component",
            "Use window.g8?.track() and window.g8?.identify() anywhere",
        ],
        "tracking_methods": _common_tracking_methods(),
    }


def _nextjs_template(write_key: str, tracking_host: str) -> dict:
    """Return Next.js snippet for both App and Pages routers."""
    app_router = _nextjs_app_router_snippet(write_key, tracking_host)
    pages_router = _nextjs_pages_router_snippet(write_key, tracking_host)
    return {
        "snippet_code": f"{app_router}\n\n{pages_router}",
        "setup_steps": [
            "App Router: add the Script to app/layout.tsx",
            "Pages Router: add the Script to pages/_app.tsx",
            "Use window.g8?.track() and window.g8?.identify() in client components",
        ],
        "tracking_methods": _common_tracking_methods(),
    }


def _nextjs_app_router_snippet(write_key: str, tracking_host: str) -> str:
    """Return the Next.js App Router code block."""
    return (
        "// app/layout.tsx (App Router)\n"
        "import Script from 'next/script';\n"
        "\n"
        "export default function RootLayout({ children }) {\n"
        "  return (\n"
        "    <html>\n"
        "      <head>\n"
        "        <Script\n"
        f'          src="{tracking_host}/p.js"\n'
        f'          data-write-key="{write_key}"\n'
        f'          data-tracking-host="{tracking_host}"\n'
        '          strategy="afterInteractive"\n'
        "        />\n"
        "      </head>\n"
        "      <body>{children}</body>\n"
        "    </html>\n"
        "  );\n"
        "}\n"
        "\n"
        "// Track events in any client component:\n"
        "// 'use client';\n"
        "// window.g8?.track('page_view', { page: '/pricing' });\n"
        "// window.g8?.identify('user-123', { email: 'user@example.com' });"
    )


def _nextjs_pages_router_snippet(write_key: str, tracking_host: str) -> str:
    """Return the Next.js Pages Router code block."""
    return (
        "// pages/_app.tsx (Pages Router)\n"
        "import Script from 'next/script';\n"
        "\n"
        "export default function App({ Component, pageProps }) {\n"
        "  return (\n"
        "    <>\n"
        "      <Script\n"
        f'        src="{tracking_host}/p.js"\n'
        f'        data-write-key="{write_key}"\n'
        f'        data-tracking-host="{tracking_host}"\n'
        '        strategy="afterInteractive"\n'
        "      />\n"
        "      <Component {...pageProps} />\n"
        "    </>\n"
        "  );\n"
        "}"
    )


def _vue_template(write_key: str, tracking_host: str) -> dict:
    """Return Vue snippet and instructions."""
    snippet = (
        "<!-- App.vue or main layout -->\n"
        "<script setup>\n"
        "import { onMounted } from 'vue';\n"
        "\n"
        "onMounted(() => {\n"
        "  const script = document.createElement('script');\n"
        f"  script.src = '{tracking_host}/p.js';\n"
        "  script.defer = true;\n"
        f"  script.dataset.writeKey = '{write_key}';\n"
        f"  script.dataset.trackingHost = '{tracking_host}';\n"
        "  document.head.appendChild(script);\n"
        "});\n"
        "\n"
        "// Composable for tracking:\n"
        "// const g8 = () => window.g8;\n"
        "// g8()?.track('event', { key: 'value' });\n"
        "// g8()?.identify('user-123', { email: 'user@example.com' });\n"
        "</script>"
    )
    return {
        "snippet_code": snippet,
        "setup_steps": [
            "Add the onMounted block to App.vue or your main layout",
            "Use window.g8?.track() and window.g8?.identify() in any component",
        ],
        "tracking_methods": _common_tracking_methods(),
    }


def _wordpress_template(write_key: str, tracking_host: str) -> dict:
    """Return WordPress snippet and instructions."""
    snippet = (
        "// Add to your theme's functions.php:\n"
        "function graph8_tracking_snippet() {\n"
        "    ?>\n"
        f'    <script src="{tracking_host}/p.js"\n'
        f'            data-write-key="{write_key}"\n'
        f'            data-tracking-host="{tracking_host}"\n'
        "            defer></script>\n"
        "    <?php\n"
        "}\n"
        "add_action('wp_head', 'graph8_tracking_snippet');"
    )
    return {
        "snippet_code": snippet,
        "setup_steps": [
            "Add the function to your theme's functions.php",
            "Alternatively, use a plugin like 'Insert Headers and Footers' "
            "and paste the script tag in the Header section",
            "Verify by viewing page source — script should appear in <head>",
        ],
        "tracking_methods": _common_tracking_methods(),
    }


def _webflow_template(write_key: str, tracking_host: str) -> dict:
    """Return Webflow snippet and instructions."""
    snippet = (
        f'<script src="{tracking_host}/p.js"\n'
        f'        data-write-key="{write_key}"\n'
        f'        data-tracking-host="{tracking_host}"\n'
        f"        defer></script>"
    )
    return {
        "snippet_code": snippet,
        "setup_steps": [
            "Go to Project Settings -> Custom Code",
            'Paste the script tag in the "Head Code" section',
            "Publish the site to apply changes",
        ],
        "tracking_methods": _common_tracking_methods(),
    }


def _shopify_template(write_key: str, tracking_host: str) -> dict:
    """Return Shopify snippet and instructions."""
    snippet = (
        "<!-- Add to theme.liquid, before </head> -->\n"
        f'<script src="{tracking_host}/p.js"\n'
        f'        data-write-key="{write_key}"\n'
        f'        data-tracking-host="{tracking_host}"\n'
        f"        defer></script>"
    )
    return {
        "snippet_code": snippet,
        "setup_steps": [
            "Go to Online Store -> Themes -> Edit Code",
            "Open theme.liquid",
            "Paste the snippet before the closing </head> tag",
            "Save the file",
        ],
        "tracking_methods": _common_tracking_methods(),
    }


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


def _common_tracking_methods() -> dict:
    """Return shared identify/track examples."""
    return {
        "identify": 'g8.identify("user-id", {email: "user@example.com", name: "Jane Doe"})',
        "track": 'g8.track("event_name", {property: "value"})',
    }


_TEMPLATE_REGISTRY: dict[str, callable] = {
    "html": _html_template,
    "react": _react_template,
    "nextjs": _nextjs_template,
    "vue": _vue_template,
    "wordpress": _wordpress_template,
    "webflow": _webflow_template,
    "shopify": _shopify_template,
}


def build_snippet_result(framework: str, write_key: str, tracking_host: str) -> dict[str, Any]:
    """Build snippet result for CLI use — no API call needed."""
    return _build_result(framework, {"write_key": write_key, "tracking_host": tracking_host})
