#!/usr/bin/env python3
"""
Documentation Sync Runner

Execute documentation generators based on manifest configuration.
"""

import json
import sys
from pathlib import Path
from typing import List, Dict, Any
import logging

# Setup logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    datefmt='%H:%M:%S'
)
logger = logging.getLogger(__name__)


class DocSyncRunner:
    """
    Documentation synchronization runner.

    Reads manifest.json and executes configured generators.
    """

    def __init__(self, project_root: Path):
        """
        Initialize runner.

        Args:
            project_root: Project root directory
        """
        self.project_root = Path(project_root)
        self.manifest_path = self.project_root / ".dss" / "doc-sync" / "manifest.json"
        self.manifest = self._load_manifest()

    def _load_manifest(self) -> Dict[str, Any]:
        """
        Load manifest.json configuration.

        Returns:
            Manifest dictionary
        """
        if not self.manifest_path.exists():
            logger.error(f"Manifest not found: {self.manifest_path}")
            sys.exit(1)

        try:
            with open(self.manifest_path, 'r') as f:
                return json.load(f)
        except Exception as e:
            logger.error(f"Failed to load manifest: {e}")
            sys.exit(1)

    def run_generators(self, trigger: str = "manual") -> None:
        """
        Run all generators configured for the given trigger.

        Args:
            trigger: Trigger type (post-commit, manual, etc.)
        """
        logger.info(f"Running documentation sync (trigger: {trigger})")

        code_mappings = self.manifest.get("sources", {}).get("code_mappings", [])

        for mapping in code_mappings:
            # Check if this generator should run for this trigger
            if trigger not in mapping.get("triggers", ["manual"]):
                logger.debug(f"Skipping {mapping['generator']} (trigger mismatch)")
                continue

            # Check if generator is enabled
            generator_config = self.manifest.get("generators", {}).get(mapping["generator"], {})
            if not generator_config.get("enabled", False):
                logger.warning(f"Generator {mapping['generator']} is disabled, skipping")
                continue

            # Run generator
            self._run_generator(mapping)

        logger.info("Documentation sync complete")

    def _run_generator(self, mapping: Dict[str, Any]) -> None:
        """
        Run a specific generator.

        Args:
            mapping: Code mapping configuration
        """
        generator_name = mapping["generator"]
        source_pattern = mapping["pattern"]
        target_path = self.project_root / mapping["extracts_to"]

        logger.info(f"Running {generator_name}: {source_pattern} → {target_path}")

        try:
            # Import generator class
            if generator_name == "api_extractor":
                from generators.api_extractor import APIExtractor
                generator = APIExtractor(self.project_root)

            elif generator_name == "mcp_extractor":
                from generators.mcp_extractor import MCPExtractor
                generator = MCPExtractor(self.project_root)

            else:
                logger.warning(f"Unknown generator: {generator_name}")
                return

            # Resolve source path (handle patterns)
            source_paths = self._resolve_source_paths(source_pattern)

            if not source_paths:
                logger.warning(f"No source files found for pattern: {source_pattern}")
                return

            # Run generator for first matching file (extend later for multiple)
            source_path = source_paths[0]
            generator.run(source_path, target_path)

            logger.info(f"✓ Generated: {target_path}")

        except Exception as e:
            logger.error(f"Failed to run {generator_name}: {e}", exc_info=True)

    def _resolve_source_paths(self, pattern: str) -> List[Path]:
        """
        Resolve source file paths from pattern.

        Args:
            pattern: File pattern (e.g., "tools/api/server.py")

        Returns:
            List of matching paths
        """
        # Simple implementation: exact match only
        # TODO: Add glob pattern support

        source_path = self.project_root / pattern

        if source_path.exists():
            return [source_path]

        return []

    def validate_manifest(self) -> bool:
        """
        Validate manifest syntax and configuration.

        Returns:
            True if valid, False otherwise
        """
        logger.info("Validating manifest.json")

        # Check required sections
        required_sections = ["sources", "generators", "git_hooks"]
        for section in required_sections:
            if section not in self.manifest:
                logger.error(f"Missing required section: {section}")
                return False

        # Check code mappings
        code_mappings = self.manifest.get("sources", {}).get("code_mappings", [])
        if not code_mappings:
            logger.error("No code mappings defined")
            return False

        logger.info("✓ Manifest is valid")
        return True


def main():
    """
    Main entry point for CLI usage.
    """
    import argparse

    parser = argparse.ArgumentParser(description="Documentation Sync Runner")
    parser.add_argument(
        "command",
        choices=["run", "validate"],
        help="Command to execute"
    )
    parser.add_argument(
        "--trigger",
        default="manual",
        help="Trigger type (post-commit, manual, etc.)"
    )
    parser.add_argument(
        "--project-root",
        type=Path,
        default=Path(__file__).parent.parent.parent,
        help="Project root directory"
    )

    args = parser.parse_args()

    runner = DocSyncRunner(args.project_root)

    if args.command == "validate":
        success = runner.validate_manifest()
        sys.exit(0 if success else 1)

    elif args.command == "run":
        runner.run_generators(trigger=args.trigger)
        sys.exit(0)


if __name__ == "__main__":
    main()
