# Copyright 2025 The RLinf Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import pathlib
import re
import sys

from docutils import nodes
from docutils.parsers.rst import roles

# Ensure project root is on Python path for autodoc
sys.path.insert(0, os.path.abspath("../../"))


# -- Project Information -------------------------------------------------------

project = "RLinf"
author = "RLinf Team"
copyright = "2025 RLinf Project"
version = "latest"


# -- General Configuration -----------------------------------------------------

extensions = [
    "myst_parser",  # Markdown support
    "sphinx.ext.mathjax",
    "sphinx_copybutton",  # “Copy” button for code blocks
    "sphinx.ext.autodoc",  # API documentation from docstrings
    "sphinx.ext.autosummary",  # Generate summary tables
    "sphinx.ext.napoleon",  # Google & NumPy style docstrings
    "sphinx_sitemap",  # Sitemap generation
    "sphinxcontrib.video",
    "sphinx_design",  # grids/cards for "At a glance" boxes
    # "sphinx.ext.viewcode", # Source code links (optional)
]

# File types for source documents
source_suffix = {
    ".rst": "restructuredtext",
    ".md": "markdown",
}

templates_path = ["_templates"]
exclude_patterns = [
    "**/_*.rst"
]  # underscore-prefixed files are reusable includes, not standalone pages
default_role = "code"
autosummary_generate = True
autodoc_mock_imports = ["sglang", "megatron", "prismatic", "libero", "lerobot"]
autodoc_class_signature = "separated"
autodoc_typehints = "description"
# autoclass_content = "both"
autodoc_docstring_signature = True
napoleon_use_param = True
napoleon_use_rtype = True
napoleon_preprocess_types = True

# Autodoc defaults: include members and inheritance
# autodoc_default_options = {
#     "members":            True,
#     "inherited-members":  True,
#     "show-inheritance":   True,
# }


# -- HTML Output Options -------------------------------------------------------
language = "en"
html_search_language = "en"
html_theme = "pydata_sphinx_theme"
html_show_sourcelink = False  # Hide “View page source” link
html_baseurl = os.environ.get(
    "READTHEDOCS_CANONICAL_URL",
    "https://rlinf.readthedocs.io/en/latest/",
)
sitemap_url_scheme = "{link}"
html_favicon = "_static/favicon.ico"
html_static_path = ["_static"]
html_css_files = [
    "css/custom.css",
    "css/sphinx-modal.css",
    "css/mode-selection.css",
]
html_js_files = [
    "typesense.min.js",
    "js/config-manager.js",
    "js/assistant-utils.js",
    "js/typesense-client.js",
    "js/message-manager.js",
    "js/ai-chat-service.js",
    "js/mode-badge.js",
    "js/mode-panel.js",
    "js/github-stars.js",
    "js/sidebar-nav.js",
    "js/lang-switcher.js",
    "js/theme-toggle.js",
    "sphinx-modal-widget.js",
]
html_sidebars = {
    "**": [
        "sidebar-brand",
        "search-field",
        "sidebar-tools",
        "global-sidebar-nav",
    ]
}


# -- Theme Options -------------------------------------------------------------


def render_svg_logo(path, width="4rem", height="auto"):
    """Embed and size an SVG logo from the static directory."""
    svg_file = pathlib.Path(__file__).parent / path
    svg_text = svg_file.read_text(encoding="utf-8")
    return re.sub(
        r"<svg\b", f'<svg width="{width}" height="{height}"', svg_text, count=1
    )


html_theme_options = {
    "logo": {"svg": render_svg_logo("_static/svg/logo.svg")},
    "search_bar_text": "Search docs…",
    "navbar_start": [],
    "navbar_center": [],
    "navbar_end": [],
    "navbar_align": "left",
    "secondary_sidebar_items": {
        "**": ["page-toc"],
        "index": [],
    },
    "collapse_navigation": False,
    "show_nav_level": 1,
    "navigation_depth": 5,
    "header_links_before_dropdown": 10,
    "icon_links": [
        {
            "name": "GitHub",
            "url": "https://github.com/RLinf/RLinf",
            "icon": "fab fa-github",
            "type": "fontawesome",
        },
    ],
    "switcher": {
        "json_url": "https://rlinf.readthedocs.io/en/latest/_static/versions.json",
        "version_match": version,
    },
}


def make_role(color):
    def role_fn(name, rawtext, text, lineno, inliner, options={}, content=[]):
        node = nodes.inline(text, text, classes=[color])
        return [node], []

    return role_fn


roles.register_local_role("red", make_role("red"))
roles.register_local_role("green", make_role("green"))


# -- HTML Context & Setup ------------------------------------------------------


def setup_html_context(app, pagename, templatename, context, doctree):
    """Inject build-time config values into templates."""
    cfg = app.config
    context.update(
        {
            "typesense_host": getattr(cfg, "typesense_host", "localhost"),
            "typesense_port": getattr(cfg, "typesense_port", 8108),
            "typesense_protocol": getattr(cfg, "typesense_protocol", "http"),
            "typesense_api_key": getattr(cfg, "typesense_api_key", ""),
            "typesense_collection": getattr(cfg, "typesense_collection", "sphinx_docs"),
            "typesense_enable_vector_search": getattr(
                cfg, "typesense_enable_vector_search", "true"
            ),
            "typesense_stopwords_set": getattr(cfg, "typesense_stopwords_set", ""),
            "sphinx_env": getattr(cfg, "sphinx_env", "development"),
            "sphinx_debug": getattr(cfg, "sphinx_debug", "false"),
        }
    )


def setup(app):
    """Register custom config values and connect context setup."""
    # Allow overriding via -D flags
    app.add_config_value(
        "typesense_host",
        os.environ.get(
            "RLINF_TYPESENSE_HOST", "typesense.product-team-dev.infini-ai.com"
        ),
        "html",
    )
    app.add_config_value(
        "typesense_port", int(os.environ.get("RLINF_TYPESENSE_PORT", "9443")), "html"
    )
    app.add_config_value(
        "typesense_protocol",
        os.environ.get("RLINF_TYPESENSE_PROTOCOL", "https"),
        "html",
    )
    app.add_config_value(
        "typesense_api_key",
        os.environ.get("RLINF_TYPESENSE_SEARCH_API_KEY", ""),
        "html",
    )
    app.add_config_value(
        "typesense_collection",
        os.environ.get("RLINF_TYPESENSE_COLLECTION", "infini-RL"),
        "html",
    )
    app.add_config_value(
        "typesense_enable_vector_search",
        os.environ.get("RLINF_TYPESENSE_ENABLE_VECTOR_SEARCH", "true"),
        "html",
    )
    app.add_config_value(
        "typesense_stopwords_set",
        os.environ.get("RLINF_TYPESENSE_STOPWORDS_SET", ""),
        "html",
    )
    app.add_config_value(
        "sphinx_env", os.environ.get("RLINF_DOCS_ENV", "development"), "html"
    )
    app.add_config_value(
        "sphinx_debug", os.environ.get("RLINF_DOCS_DEBUG", "false"), "html"
    )

    app.connect("html-page-context", setup_html_context)
    app.add_css_file("css/custom.css")

    return {
        "version": "0.2",
        "parallel_read_safe": True,
        "parallel_write_safe": True,
    }
