"""
Pair Puzzle Directive
=====================

A Sphinx directive for creating interactive pairing puzzles where users drag and drop
items to match pairs. Uses KaTeX for math rendering.

Usage:
    .. pair-puzzle::
        :class: optional-css-class

        Left item 1 : Right item 1
        Left item 2 : Right item 2
        Left item 3 : Right item 3

The directive accepts content as pairs separated by ':'. Each line represents a pair
that the user must match. Items can contain HTML, LaTeX math (using $ or $$), or code blocks.

Example:
    .. pair-puzzle::

        $x^2 + 2x + 1$ : $(x+1)^2$
        $\\sin^2(x) + \\cos^2(x)$ : $1$
        <code>print("hello")</code> : Python output function

MyST Syntax (colon-fence):
    :::{pairpuzzle}
    :class: optional-css-class

    Left item 1 : Right item 1
    Left item 2 : Right item 2
    :::

Note: Due to MyST limitations with hyphens in directive names when using colon-fence
syntax (:::), the directive is also registered as "pairpuzzle" (no hyphen).
"""

from docutils import nodes
from docutils.parsers.rst import Directive
from docutils.parsers.rst import directives
from sphinx.application import Sphinx
import uuid


class PairPuzzleNode(nodes.General, nodes.Element):
    """Custom docutils node for pair puzzles."""

    pass


class PairPuzzleDirective(Directive):
    """
    Directive for creating interactive pairing puzzles.

    The directive parses content as colon-separated pairs and generates
    HTML/JavaScript for an interactive drag-and-drop game.
    """

    has_content = True
    option_spec = {
        "class": directives.class_option,
    }

    def run(self):
        """Parse the directive content and create the puzzle node."""
        # Generate unique container ID
        container_id = f"pair-puzzle-{uuid.uuid4()}"

        # Parse pairs from content
        pairs = self._parse_pairs()

        if not pairs:
            error = self.state_machine.reporter.error(
                'pair-puzzle directive requires at least one pair (format: "left : right")',
                nodes.literal_block(self.block_text, self.block_text),
                line=self.lineno,
            )
            return [error]

        # Create the custom node
        node = PairPuzzleNode()
        node["container_id"] = container_id
        node["pairs"] = pairs
        node["classes"] = self.options.get("class", [])

        return [node]

    def _parse_pairs(self):
        """
        Parse content into pairs.

        Expected format:
            Left item 1 : Right item 1
            Left item 2 : Right item 2

        Returns:
            List of tuples [(left1, right1), (left2, right2), ...]
        """
        pairs = []
        for line in self.content:
            line = line.strip()
            if not line:
                continue

            # Split on first ':' only
            if ":" in line:
                left, right = line.split(":", 1)
                pairs.append((left.strip(), right.strip()))
            else:
                # Skip lines without ':' separator
                continue

        return pairs


def visit_pair_puzzle_html(self, node):
    """Generate HTML for the pair puzzle."""
    container_id = node["container_id"]
    pairs = node["pairs"]
    extra_classes = " ".join(node["classes"])

    # Build JavaScript pairs array
    js_pairs = []
    for left, right in pairs:
        js_pairs.append(f'["{left}", "{right}"]')

    pairs_js = ",\n        ".join(js_pairs)

    # Generate HTML container
    html = f"""
<div id="{container_id}" class="pairing-puzzle-container {extra_classes}">
    <!-- Content will be generated by JavaScript -->
</div>

<script>
  // Initialize the pairing puzzle when DOM is ready
  (function() {{
    function initPuzzle() {{
      const pairs = [
        {pairs_js}
      ];
      
      // Check if initGame is available
      if (typeof initGame === 'function') {{
        initGame('{container_id}', pairs);
      }} else {{
        console.error('initGame function not found. Make sure game.js is loaded.');
      }}
    }}
    
    // Wait for DOM and required dependencies
    if (document.readyState === 'loading') {{
      document.addEventListener('DOMContentLoaded', initPuzzle);
    }} else {{
      initPuzzle();
    }}
  }})();
</script>
"""

    self.body.append(html)


def depart_pair_puzzle_html(self, node):
    """No closing tags needed."""
    pass


def setup(app: Sphinx):
    """
    Setup the pair-puzzle directive.

    Registers the directive under two names:
    - "pair-puzzle" for RST compatibility
    - "pairpuzzle" for MyST colon-fence compatibility (no hyphens allowed)
    """
    # Register the custom node
    app.add_node(PairPuzzleNode, html=(visit_pair_puzzle_html, depart_pair_puzzle_html))

    # Register directive with both names for compatibility
    app.add_directive("pair-puzzle", PairPuzzleDirective)
    app.add_directive("pairpuzzle", PairPuzzleDirective)  # MyST compatibility

    # Note: CSS and JS files are registered in __init__.py with the munchboka/ prefix
    # No need to register them here to avoid duplicate/incorrect paths

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