"""
Splunk documentation resources for MCP server.

Provides version-aware access to Splunk documentation, optimized for LLM consumption.
"""

import logging
from datetime import datetime, timedelta
from typing import Any

from fastmcp import Context

try:
    import httpx

    HAS_HTTPX = True
except ImportError:
    HAS_HTTPX = False

from src.core.base import BaseResource, ResourceMetadata
from src.core.registry import resource_registry

from .processors.html_processor import SplunkDocsProcessor

logger = logging.getLogger(__name__)


class DocumentationCache:
    """Version-aware caching for Splunk documentation."""

    def __init__(self, ttl_hours: int = 24):
        self.cache: dict[str, dict[str, Any]] = {}
        self.ttl_hours = ttl_hours

    def cache_key(self, version: str, category: str, topic: str) -> str:
        """Generate cache key for documentation."""
        return f"docs_{version}_{category}_{topic}"

    def is_expired(self, timestamp: datetime) -> bool:
        """Check if cached item is expired."""
        return datetime.now() - timestamp > timedelta(hours=self.ttl_hours)

    async def get_or_fetch(self, version: str, category: str, topic: str, fetch_func) -> str:
        """Get from cache or fetch if expired/missing."""
        key = self.cache_key(version, category, topic)

        if key in self.cache:
            cached_item = self.cache[key]
            if not self.is_expired(cached_item["timestamp"]):
                logger.debug(f"Cache hit for {key}")
                return cached_item["content"]

        # Fetch fresh content
        logger.debug(f"Cache miss for {key}, fetching")
        content = await fetch_func()
        self.cache[key] = {"content": content, "timestamp": datetime.now(), "version": version}

        return content

    def invalidate_version(self, version: str):
        """Invalidate all cached docs for a specific version."""
        keys_to_remove = [k for k in self.cache.keys() if k.startswith(f"docs_{version}_")]
        for key in keys_to_remove:
            del self.cache[key]
        logger.info(f"Invalidated {len(keys_to_remove)} cache entries for version {version}")


# Global documentation cache
_doc_cache = DocumentationCache()


class SplunkDocsResource(BaseResource):
    """Base class for Splunk documentation resources."""

    # SPLUNK_DOCS_BASE = "https://docs.splunk.com"
    SPLUNK_HELP_BASE = "https://help.splunk.com"
    VERSION_MAPPING = {
        "10.0.0": "10.0",
        "9.4.0": "9.4",
        "9.3.0": "9.3",
        "9.2.1": "9.2",
        "9.1.0": "9.1",
        "latest": "10.0",  # Current latest
    }

    def __init__(self, uri: str, name: str, description: str, mime_type: str = "text/markdown"):
        super().__init__(uri, name, description, mime_type)
        self.processor = SplunkDocsProcessor()

    async def get_splunk_version(self, ctx: Context) -> str:
        """Detect Splunk version from connected instance."""
        try:
            # Import here to avoid circular imports
            from src.tools.health.status import GetSplunkHealth

            health_tool = GetSplunkHealth("get_splunk_health", "Get Splunk health status")
            health_result = await health_tool.execute(ctx)

            if health_result.get("status") == "connected":
                version = health_result.get("version", "latest")
                logger.debug(f"Detected Splunk version: {version}")
                return version
        except Exception as e:
            logger.warning(f"Failed to detect Splunk version: {e}")

        return "latest"

    def normalize_version(self, version: str) -> str:
        """Convert version to docs URL format."""
        # Handle auto-detection
        if version == "auto":
            version = "latest"

        # Extract major.minor from full version if needed
        if version not in self.VERSION_MAPPING:
            # Try to match major.minor (e.g., "9.3.1" -> "9.3.0")
            parts = version.split(".")
            if len(parts) >= 2:
                major_minor = f"{parts[0]}.{parts[1]}.0"
                if major_minor in self.VERSION_MAPPING:
                    version = major_minor

        return self.VERSION_MAPPING.get(version, self.VERSION_MAPPING["latest"])

    def format_version_for_help_url(self, version: str) -> str:
        """Convert version to help URL format.

        Takes a version string (e.g., "9.4.0", "latest", "auto") and returns
        the normalized version suitable for help.splunk.com URLs (e.g., "9.4").
        """
        norm_version = self.normalize_version(version)
        return norm_version

    async def fetch_doc_content(self, url: str) -> str:
        """Fetch and process documentation content."""
        if not HAS_HTTPX:
            return f"""# Documentation Unavailable

HTTP client not available. To enable documentation fetching, install httpx:

```bash
pip install httpx
```

**Requested URL**: {url}
**Time**: {datetime.now().isoformat()}
"""

        try:
            # Headers to bypass browser detection on help.splunk.com
            headers = {
                "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
            }

            async with httpx.AsyncClient(
                timeout=30.0, headers=headers, follow_redirects=True
            ) as client:
                logger.debug(f"Fetching documentation from: {url}")
                response = await client.get(url)
                response.raise_for_status()

                # Process HTML to LLM-friendly format
                content = self.processor.process_html(response.text, url)
                logger.debug(f"Successfully processed documentation from {url}")
                return content

        except httpx.HTTPStatusError as e:
            if e.response.status_code == 404:
                return f"""# Documentation Not Found

The requested Splunk documentation was not found at this URL.

**URL**: {url}
**Status**: 404 Not Found
**Time**: {datetime.now().isoformat()}

This may indicate:
- The documentation has moved or been renamed
- The Splunk version doesn't have this specific documentation
- The topic name may be incorrect

Please check the [Splunk Documentation](https://help.splunk.com) for the correct location.
"""
            else:
                return f"""# Documentation Error

Failed to fetch documentation due to HTTP error.

**URL**: {url}
**Status**: {e.response.status_code}
**Error**: {str(e)}
**Time**: {datetime.now().isoformat()}
"""
        except Exception as e:
            logger.error(f"Error fetching documentation from {url}: {e}")
            return f"""# Documentation Error

Failed to fetch documentation due to an error.

**URL**: {url}
**Error**: {str(e)}
**Time**: {datetime.now().isoformat()}

Please check your internet connection and try again.
"""


class SplunkCheatSheetResource(SplunkDocsResource):
    """Static Splunk cheat sheet resource from Splunk blog."""

    METADATA = ResourceMetadata(
        uri="splunk-docs://cheat-sheet",
        name="splunk_cheat_sheet",
        description="Splunk SPL cheat sheet with commands, regex, and query examples",
        mime_type="text/markdown",
        category="reference",
        tags=["cheat-sheet", "spl", "reference", "commands", "regex"],
    )

    def __init__(
        self,
        uri: str = None,
        name: str = None,
        description: str = None,
        mime_type: str = "text/markdown",
    ):
        # Use metadata defaults if not provided
        uri = uri or self.METADATA.uri
        name = name or self.METADATA.name
        description = description or self.METADATA.description
        super().__init__(uri, name, description, mime_type)

    async def get_content(self, ctx: Context) -> str:
        """Get Splunk cheat sheet content."""

        async def fetch_cheat_sheet():
            # Use the custom processor that returns the complete cheat sheet content
            url = "https://www.splunk.com/en_us/blog/learn/splunk-cheat-sheet-query-spl-regex-commands.html"
            # The processor will handle this URL specially and return comprehensive content
            content = self.processor.process_cheat_sheet_content("", url)
            return content

        return await _doc_cache.get_or_fetch("static", "cheat-sheet", "main", fetch_cheat_sheet)


class TroubleshootingResource(SplunkDocsResource):
    """Version-aware Splunk troubleshooting documentation."""

    METADATA = ResourceMetadata(
        uri="splunk-docs://{version}/troubleshooting/{topic}",
        name="troubleshooting_guide",
        description="Splunk troubleshooting documentation for various topics and versions",
        mime_type="text/markdown",
        category="troubleshooting",
        tags=["troubleshooting", "documentation", "diagnostics", "performance"],
    )

    # Comprehensive troubleshooting topics mapping
    TROUBLESHOOTING_TOPICS = {
        # Log files and internal logging
        "splunk-logs": {
            "title": "What Splunk Logs about Itself",
            "description": "Understanding Splunk's internal logging and log files",
            "url_path": "splunk-enterprise-log-files/what-splunk-software-logs-about-itself",
        },
        "metrics-log": {
            "title": "About metrics.log",
            "description": "Understanding Splunk's metrics.log file for performance monitoring",
            "url_path": "splunk-enterprise-log-files/about-metrics.log",
        },
        "troubleshoot-inputs": {
            "title": "Troubleshooting Inputs with metrics.log",
            "description": "Using metrics.log to diagnose input-related issues",
            "url_path": "splunk-enterprise-log-files/troubleshoot-inputs-with-metrics.log",
        },
        # Platform instrumentation
        "platform-instrumentation": {
            "title": "About Platform Instrumentation",
            "description": "Understanding Splunk Enterprise platform instrumentation",
            "url_path": "platform-instrumentation/about-splunk-enterprise-platform-instrumentation",
        },
        "platform-instrumentation-logs": {
            "title": "What Platform Instrumentation Logs",
            "description": "Understanding what platform instrumentation logs in Splunk",
            "url_path": "platform-instrumentation/what-does-platform-instrumentation-log",
        },
        "platform-instrumentation-searches": {
            "title": "Sample Platform Instrumentation Searches",
            "description": "Example searches for monitoring platform instrumentation",
            "url_path": "platform-instrumentation/sample-platform-instrumentation-searches",
        },
        # Search and web problems
        "search-problems": {
            "title": "Splunk Web and Search Problems",
            "description": "Troubleshooting Splunk web interface and search issues",
            "url_path": "splunk-web-and-search-problems/i-cant-find-my-data",
        },
        "authentication-timeouts": {
            "title": "Intermittent Authentication Timeouts on Search Peers",
            "description": "Resolving authentication timeout issues between search head and peers",
            "url_path": "splunk-web-and-search-problems/intermittent-authentication-timeouts-on-search-peers",
        },
        # Data acquisition and indexing
        "indexing-performance": {
            "title": "Identify and Triage Indexing Performance Issues",
            "description": "Diagnosing and resolving indexing performance problems",
            "url_path": "data-acquisition-problems/identify-and-triage-indexing-performance-problems",
        },
        "indexing-delay": {
            "title": "Event Indexing Delay",
            "description": "Understanding and resolving event indexing delays",
            "url_path": "data-acquisition-problems/event-indexing-delay",
        },
    }

    def __init__(self, version: str, topic: str):
        self.version = version
        self.topic = topic

        if topic not in self.TROUBLESHOOTING_TOPICS:
            available_topics = ", ".join(self.TROUBLESHOOTING_TOPICS.keys())
            raise ValueError(
                f"Unknown troubleshooting topic: {topic}. Available topics: {available_topics}"
            )

        topic_info = self.TROUBLESHOOTING_TOPICS[topic]
        uri = f"splunk-docs://{version}/troubleshooting/{topic}"

        super().__init__(
            uri=uri,
            name=f"troubleshooting_{topic}_{version}",
            description=f"Splunk troubleshooting: {topic_info['description']} (version {version})",
        )

    async def get_content(self, ctx: Context) -> str:
        """Get troubleshooting documentation for specific topic."""

        async def fetch_troubleshooting_docs():
            topic_info = self.TROUBLESHOOTING_TOPICS[self.topic]
            help_version = self.format_version_for_help_url(self.version)

            url = f"{self.SPLUNK_HELP_BASE}/en/splunk-enterprise/administer/troubleshoot/{help_version}/{topic_info['url_path']}"

            content = await self.fetch_doc_content(url)

            result = f"""# Splunk Troubleshooting: {topic_info["title"]}

**Version**: Splunk {self.version}
**Category**: Troubleshooting Guide
**Topic**: {topic_info["description"]}
**Source URL**: {url}

{content}

## Troubleshooting Context

This documentation is part of Splunk's comprehensive troubleshooting guide. It helps administrators and users:

- Understand Splunk's internal operations
- Diagnose performance and operational issues
- Monitor system health and metrics
- Resolve common problems

### Related Troubleshooting Topics

"""

            # Add links to related troubleshooting topics
            for topic_key, topic_data in self.TROUBLESHOOTING_TOPICS.items():
                if topic_key != self.topic:
                    result += f"- [{topic_data['title']}](splunk-docs://{self.version}/troubleshooting/{topic_key})\n"

            result += f"""
### Additional Resources

For more troubleshooting information, see:
- [Splunk Documentation](splunk-docs://{self.version}/admin/monitoring)
- [SPL Reference](splunk-docs://{self.version}/spl-reference)
- [Splunk Cheat Sheet](splunk-docs://cheat-sheet)

---
**Generated**: {datetime.now().isoformat()}
"""

            return result

        return await _doc_cache.get_or_fetch(
            self.version, "troubleshooting", self.topic, fetch_troubleshooting_docs
        )


class SPLReferenceResource(SplunkDocsResource):
    """SPL (Search Processing Language) reference documentation."""

    METADATA = ResourceMetadata(
        uri="splunk-docs://spl-reference",
        name="spl_reference",
        description="Splunk SPL command and function reference documentation",
        mime_type="text/markdown",
        category="reference",
        tags=["spl", "search", "commands", "reference"],
    )

    def __init__(
        self,
        uri: str = None,
        name: str = None,
        description: str = None,
        mime_type: str = "text/markdown",
    ):
        # Use metadata defaults if not provided
        uri = uri or self.METADATA.uri
        name = name or self.METADATA.name
        description = description or self.METADATA.description
        super().__init__(uri, name, description, mime_type)

    async def get_content(self, ctx: Context) -> str:
        """Get SPL reference documentation content."""
        # This is a template resource - actual content comes from parameterized URIs
        return """# SPL Reference Documentation

This resource provides access to Splunk's Search Processing Language (SPL) documentation.

## Available Resources

Use these URI patterns to access specific SPL documentation:

- `splunk-docs://{version}/spl-reference/{command}` - Specific SPL command documentation
- `splunk-docs://latest/spl-reference/search` - Search command documentation
- `splunk-docs://latest/spl-reference/stats` - Stats command documentation
- `splunk-docs://latest/spl-reference/eval` - Eval command documentation

## Examples

- `splunk-docs://9.3.0/spl-reference/chart` - Chart command for Splunk 9.3.0
- `splunk-docs://latest/spl-reference/timechart` - Timechart command (latest version)

Replace `{version}` with a specific Splunk version (e.g., "9.3.0") or use "latest" for the current version.
Replace `{command}` with the SPL command name you want to learn about.
"""


class SPLCommandResource(SplunkDocsResource):
    """Specific SPL command documentation resource."""

    METADATA = ResourceMetadata(
        uri="splunk-docs://{version}/spl-reference/{command}",
        name="spl_command_reference",
        description="Splunk SPL command documentation for specific commands and versions",
        mime_type="text/markdown",
        category="reference",
        tags=["spl", "commands", "reference", "search"],
    )

    def __init__(self, version: str, command: str):
        self.version = version
        self.command = command

        uri = f"splunk-docs://{version}/spl-reference/{command}"
        super().__init__(
            uri=uri,
            name=f"spl_command_{command}_{version}",
            description=f"SPL {command} command documentation for Splunk {version}",
        )

    async def get_content(self, ctx: Context) -> str:
        """Get documentation for specific SPL command."""

        async def fetch_command_docs():
            norm_version = self.normalize_version(self.version)
            # help.splunk.com uses lowercase command names and different URL structure
            command_lower = self.command.lower()
            url = f"{self.SPLUNK_HELP_BASE}/en/splunk-enterprise/search/spl-search-reference/{norm_version}/search-commands/{command_lower}"

            content = await self.fetch_doc_content(url)

            # Add SPL-specific context
            return f"""# SPL Command: {self.command}

**Version**: Splunk {self.version}
**Category**: Search Processing Language Reference

{content}

## Usage Context

The `{self.command}` command is part of Splunk's Search Processing Language (SPL). It can be used in search queries and combined with other SPL commands using the pipe (|) operator.

### Common Usage Patterns

```spl
index=main | {self.command} ...
```

For more SPL commands, see the complete [SPL Reference](splunk-docs://{self.version}/spl-reference).
"""

        return await _doc_cache.get_or_fetch(
            self.version, "spl-reference", self.command, fetch_command_docs
        )


class AdminGuideResource(SplunkDocsResource):
    """Splunk administration documentation."""

    METADATA = ResourceMetadata(
        uri="splunk-docs://{version}/admin/{topic}",
        name="admin_guide",
        description="Splunk administration documentation for various topics and versions",
        mime_type="text/markdown",
        category="administration",
        tags=["administration", "configuration", "management", "deployment"],
    )

    def __init__(self, version: str, topic: str):
        self.version = version
        self.topic = topic

        uri = f"splunk-docs://{version}/admin/{topic}"
        super().__init__(
            uri=uri,
            name=f"admin_{topic}_{version}",
            description=f"Splunk administration guide: {topic} (version {version})",
        )

    async def get_content(self, ctx: Context) -> str:
        """Get administration documentation for specific topic."""

        async def fetch_admin_docs():
            # help.splunk.com uses hyphenated topic names and different URL structure
            topic_url = self.topic.replace("_", "-").lower()
            url = f"{self.SPLUNK_HELP_BASE}/en/splunk-enterprise/administer/{topic_url}"

            content = await self.fetch_doc_content(url)

            return f"""# Splunk Administration: {self.topic}

**Version**: Splunk {self.version}
**Category**: Administration Guide

{content}

## Administration Context

This documentation covers administrative aspects of Splunk deployment and configuration.

For related administration topics, see the complete [Admin Guide](splunk-docs://{self.version}/admin).
"""

        return await _doc_cache.get_or_fetch(self.version, "admin", self.topic, fetch_admin_docs)


class SplunkSpecReferenceResource(SplunkDocsResource):
    """Splunk configuration specification file reference documentation."""

    METADATA = ResourceMetadata(
        uri="splunk-spec://{config}",
        name="splunk_spec_reference",
        description="Splunk configuration specification reference (auto-detects version)",
        mime_type="text/markdown",
        category="reference",
        tags=["spec", "configuration", "reference", "admin"],
    )

    def __init__(self, config: str):
        self.config = config
        # Version will be detected dynamically in get_content()
        self._cached_version = None

        uri = f"splunk-spec://{config}"
        # Normalize config name for display
        display_config = self._normalize_config_name(config)
        super().__init__(
            uri=uri,
            name=f"spec_{config.replace('.', '_')}",
            description=f"Splunk configuration spec for {display_config} (auto-detected version)",
        )

    def _parse_version_components(self, version: str) -> tuple[str, str]:
        """Parse version into minor (X.Y) and full (X.Y.Z) components.

        Args:
            version: Version string like "10.0", "9.4.0", "latest", "auto"

        Returns:
            Tuple of (minor, full) version strings
        """
        # Handle auto-detection
        if version == "auto":
            version = "latest"

        # Normalize using existing method to get minor version
        minor = self.normalize_version(version)

        # Now construct full version
        # If input was already X.Y.Z, try to preserve it
        parts = version.split(".")
        if len(parts) >= 3:
            # Has patch version already
            full = f"{parts[0]}.{parts[1]}.{parts[2]}"
        elif len(parts) == 2:
            # Only has major.minor, add .0 for patch
            full = f"{parts[0]}.{parts[1]}.0"
        else:
            # Single component or "latest" - use minor + .0
            full = f"{minor}.0"

        return minor, full

    def _normalize_config_name(self, config: str) -> str:
        """Normalize configuration file name to ensure .conf extension.

        Args:
            config: Config file name (with or without .conf)

        Returns:
            Config name with .conf extension
        """
        # Always use .conf (not .conf.spec)
        if config.endswith(".conf.spec"):
            # Strip .spec suffix if present
            return config[:-5]  # Remove ".spec"
        elif config.endswith(".conf"):
            return config
        else:
            return f"{config}.conf"

    async def get_content(self, ctx: Context) -> str:
        """Get configuration specification documentation for specific file."""

        # Detect version once before caching
        version = await self.get_splunk_version(ctx)
        logger.info(f"Auto-detected Splunk version: {version}")

        async def fetch_spec_docs():
            # Version already detected above
            minor, full = self._parse_version_components(version)
            config = self._normalize_config_name(self.config)

            # Primary URL pattern (most common)
            primary_url = f"{self.SPLUNK_HELP_BASE}/en/splunk-enterprise/administer/admin-manual/{minor}/configuration-file-reference/{full}-configuration-file-reference/{config}"

            # Fallback URL pattern (alternative IA structure)
            fallback_url = f"{self.SPLUNK_HELP_BASE}/en/data-management/splunk-enterprise-admin-manual/{minor}/configuration-file-reference/{full}-configuration-file-reference/{config}"

            # Try primary URL first
            content = await self.fetch_doc_content(primary_url)
            used_url = primary_url

            # If primary fails with 404, try fallback
            if content.startswith("# Documentation Not Found"):
                logger.debug("Primary URL failed for %s, trying fallback: %s", config, fallback_url)
                fallback_content = await self.fetch_doc_content(fallback_url)

                # Use fallback if it succeeds
                if not fallback_content.startswith("# Documentation Not Found"):
                    content = fallback_content
                    used_url = fallback_url
                else:
                    # Both failed - provide helpful error
                    return f"""# Configuration Spec Not Found

The requested Splunk configuration specification was not found.

**Config File**: {config}
**Version**: {version} (minor: {minor}, full: {full})
**Time**: {datetime.now().isoformat()}

**Attempted URLs**:
1. Primary: {primary_url}
2. Fallback: {fallback_url}

This may indicate:
- The configuration file name is incorrect or has a typo
- This Splunk version doesn't document this configuration file
- The documentation structure has changed

**Common configuration files**:
- alert_actions.conf
- limits.conf
- indexes.conf
- inputs.conf
- outputs.conf
- props.conf
- transforms.conf
- server.conf
- web.conf
- authentication.conf

Please verify the configuration file name and version, or check the [Splunk Documentation](https://help.splunk.com) directly.
"""

            # Wrap successful content with metadata
            result = f"""# Splunk Configuration Spec: {config}

**Version**: Splunk {version}
**Category**: Configuration File Reference
**Source URL**: {used_url}

{content}

## Configuration Context

This documentation describes the configuration specification for `{config}`. Configuration files in Splunk Enterprise:

- Control behavior and features of the Splunk platform
- Use INI-style stanza format with key-value pairs
- Follow precedence rules (system → local → app → user)
- Can be validated using `btool check`

### Related Resources

- [Configuration File Precedence](splunk-docs://{version}/admin/configuration-file-precedence)
- [List of Configuration Files](splunk-docs://{version}/admin/list-of-configuration-files)
- [Admin Guide](splunk-docs://{version}/admin)

---
**Generated**: {datetime.now().isoformat()}
"""
            return result

        return await _doc_cache.get_or_fetch(
            version, "spec-reference", self.config, fetch_spec_docs
        )


class DocumentationDiscoveryResource(SplunkDocsResource):
    """Resource for discovering available Splunk documentation."""

    METADATA = ResourceMetadata(
        uri="splunk-docs://discovery",
        name="documentation_discovery",
        description="Discover available Splunk documentation resources",
        mime_type="text/markdown",
        category="discovery",
        tags=["discovery", "documentation", "reference"],
    )

    def __init__(
        self,
        uri: str = None,
        name: str = None,
        description: str = None,
        mime_type: str = "text/markdown",
    ):
        # Use metadata defaults if not provided
        uri = uri or self.METADATA.uri
        name = name or self.METADATA.name
        description = description or self.METADATA.description
        super().__init__(uri, name, description, mime_type)

    async def get_content(self, ctx: Context) -> str:
        """Discover available Splunk documentation resources."""

        # Try to get actual Splunk version
        try:
            detected_version = await self.get_splunk_version(ctx)
        except Exception:
            detected_version = "latest"

        # Common SPL commands for quick reference
        common_spl_commands = [
            "search",
            "stats",
            "eval",
            "chart",
            "timechart",
            "table",
            "sort",
            "where",
            "join",
            "append",
            "lookup",
            "rex",
            "fieldsfor",
            "top",
            "rare",
            "transaction",
            "streamstats",
            "eventstats",
            "bucket",
            "dedup",
            "head",
            "tail",
            "regex",
            "replace",
            "convert",
            "makemv",
            "mvexpand",
            "spath",
            "xmlkv",
            "kvform",
        ]

        # Common admin topics
        admin_topics = [
            "indexes",
            "authentication",
            "deployment",
            "apps",
            "users",
            "roles",
            "monitoring",
            "performance",
            "clustering",
            "distributed-search",
            "forwarders",
            "inputs",
            "outputs",
            "licensing",
            "security",
        ]

        # All available troubleshooting topics
        troubleshooting_topics = list(TroubleshootingResource.TROUBLESHOOTING_TOPICS.keys())

        content = f"""# Splunk Documentation Discovery

**Detected Splunk Version**: {detected_version}
**Discovery Time**: {datetime.now().isoformat()}

This resource helps you discover and access Splunk documentation through the MCP server.

## Static Resources

### 📋 Splunk Cheat Sheet
- **URI**: `splunk-docs://cheat-sheet`
- **Description**: Complete SPL command reference, regex patterns, and quick examples
- **Source**: Official Splunk blog

## Dynamic Resources

### 🔍 SPL Command Reference
Access documentation for specific SPL commands:

**Pattern**: `splunk-docs://{{version}}/spl-reference/{{command}}`

**Common Commands**:
"""

        # Add SPL commands in columns
        for i, cmd in enumerate(common_spl_commands):
            if i % 4 == 0:
                content += "\n"
            content += f"- [`{cmd}`](splunk-docs://{detected_version}/spl-reference/{cmd})  "

        content += """

### 🛠️ Troubleshooting Documentation
Access version-specific troubleshooting guides:

**Pattern**: `splunk-docs://{version}/troubleshooting/{topic}`

**Available Topics**:
"""

        # Add troubleshooting topics with descriptions
        for topic in troubleshooting_topics:
            topic_info = TroubleshootingResource.TROUBLESHOOTING_TOPICS[topic]
            content += f"- [`{topic}`](splunk-docs://{detected_version}/troubleshooting/{topic}) - {topic_info['description']}\n"

        content += """

### ⚙️ Administration Guides
Access administration documentation:

**Pattern**: `splunk-docs://{version}/admin/{topic}`

**Common Topics**:
"""

        # Add admin topics in columns
        for i, topic in enumerate(admin_topics):
            if i % 3 == 0:
                content += "\n"
            content += f"- [`{topic}`](splunk-docs://{detected_version}/admin/{topic})  "

        # Common configuration files for spec reference
        common_config_files = [
            "alert_actions.conf",
            "limits.conf",
            "indexes.conf",
            "inputs.conf",
            "outputs.conf",
            "props.conf",
            "transforms.conf",
            "server.conf",
            "web.conf",
            "authentication.conf",
            "authorize.conf",
            "savedsearches.conf",
        ]

        content += """

### 🧩 Configuration Spec Reference
Access configuration file specifications:

**Pattern**: `splunk-spec://{config}`

**💡 Pro Tip**: Version is automatically detected from your connected Splunk instance!

**Common Configuration Files**:
"""

        # Add config files in columns
        for i, config in enumerate(common_config_files):
            if i % 3 == 0:
                content += "\n"
            content += f"- [`{config}`](splunk-spec://{config})  "

        content += f"""

## Version Support

**Supported Versions**: 9.1.0, 9.2.1, 9.3.0, 9.4.0, 10.0.0, latest
**Default Version**: latest (currently 10.0.0)
**Auto-Detection**: Version automatically detected from your connected Splunk instance

### Examples

```
# Static resources (no version needed)
splunk-docs://cheat-sheet

# Dynamic resources with version
splunk-docs://9.4/troubleshooting/metrics-log
splunk-docs://latest/spl-reference/stats
splunk-docs://9.3.0/admin/indexes

# Configuration spec references (version auto-detected)
splunk-spec://alert_actions.conf
splunk-spec://limits.conf
splunk-spec://inputs.conf
splunk-spec://props.conf
splunk-spec://transforms.conf

# Auto-detect version for other resources (uses detected: {detected_version})
splunk-docs://auto/troubleshooting/platform-instrumentation
```

## Quick Access Links

### Most Useful Resources
- [📋 Splunk Cheat Sheet](splunk-docs://cheat-sheet) - Essential SPL reference
- [🔧 Metrics Log Troubleshooting](splunk-docs://{detected_version}/troubleshooting/metrics-log) - Performance monitoring
- [📊 Platform Instrumentation](splunk-docs://{detected_version}/troubleshooting/platform-instrumentation) - System monitoring
- [🔍 Search Problems](splunk-docs://{detected_version}/troubleshooting/search-problems) - Search troubleshooting
- [📈 Indexing Performance](splunk-docs://{detected_version}/troubleshooting/indexing-performance) - Index optimization

### For Administrators
- [👥 User Management](splunk-docs://{detected_version}/admin/users) - User administration
- [🏗️ Index Management](splunk-docs://{detected_version}/admin/indexes) - Index configuration
- [🔐 Authentication](splunk-docs://{detected_version}/admin/authentication) - Security setup
- [📡 Distributed Search](splunk-docs://{detected_version}/admin/distributed-search) - Multi-instance setup

### Configuration References
- [🔧 Alert Actions Spec](splunk-spec://{detected_version}/alert_actions.conf) - Alert configuration
- [⚡ Limits Spec](splunk-spec://{detected_version}/limits.conf) - Performance tuning
- [📊 Indexes Spec](splunk-spec://{detected_version}/indexes.conf) - Index configuration
- [📥 Inputs Spec](splunk-spec://{detected_version}/inputs.conf) - Data input configuration

---

**Note**: All documentation is cached for 24 hours for optimal performance. URLs are automatically validated and content is processed for LLM consumption.
"""

        return content


# Registry and factory functions
def register_all_resources():
    """Register all documentation resources with the resource registry."""
    try:
        # Register static resources that have METADATA defined
        resource_registry.register(SplunkCheatSheetResource, SplunkCheatSheetResource.METADATA)

        resource_registry.register(
            DocumentationDiscoveryResource, DocumentationDiscoveryResource.METADATA
        )

        resource_registry.register(SPLReferenceResource, SPLReferenceResource.METADATA)

        # Register dynamic/parameterized resources using their class METADATA
        resource_registry.register(TroubleshootingResource, TroubleshootingResource.METADATA)
        resource_registry.register(SPLCommandResource, SPLCommandResource.METADATA)
        resource_registry.register(AdminGuideResource, AdminGuideResource.METADATA)
        resource_registry.register(
            SplunkSpecReferenceResource, SplunkSpecReferenceResource.METADATA
        )

        logger.info(
            "Successfully registered 7 Splunk documentation resources (3 static, 4 dynamic templates)"
        )

    except Exception as e:
        logger.error(f"Failed to register documentation resources: {e}")


def create_spl_command_resource(version: str, command: str) -> SPLCommandResource:
    """Factory function to create SPL command documentation resources."""
    return SPLCommandResource(version, command)


def create_admin_guide_resource(version: str, topic: str) -> AdminGuideResource:
    """Factory function to create admin guide documentation resources."""
    return AdminGuideResource(version, topic)


def create_troubleshooting_resource(version: str, topic: str) -> TroubleshootingResource:
    """Factory function to create troubleshooting documentation resources."""
    return TroubleshootingResource(version, topic)


def create_spec_reference_resource(config: str) -> SplunkSpecReferenceResource:
    """Factory function to create configuration spec reference resources.

    Args:
        config: Configuration file name (e.g., "alert_actions.conf", "limits.conf")

    Returns:
        SplunkSpecReferenceResource instance (version auto-detected from Splunk instance)
    """
    return SplunkSpecReferenceResource(config)


# Auto-register resources when module is imported
register_all_resources()
