#!/usr/bin/env python3
"""
Ralph Superpowers Integration

Complete integration of oh-my-opencode and superpowers features.
This module dynamically loads, configures, and makes available all skills,
agents, hooks, and MCPs from both projects for use in Claude Code CLI.
"""

import os
import sys
import json
import shutil
import subprocess
import logging
from pathlib import Path
from typing import Dict, List, Optional, Any, Callable
from dataclasses import dataclass, field
from enum import Enum
import importlib.util

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger('ralph.superpowers')


class IntegrationType(Enum):
    """Types of integrations"""
    SKILL = "skill"
    HOOK = "hook"
    AGENT = "agent"
    MCP = "mcp"
    COMMAND = "command"
    TOOL = "tool"


@dataclass
class IntegrationModule:
    """Represents an integrated module"""
    name: str
    type: IntegrationType
    source: str  # oh-my-opencode, superpowers, contains-studio
    path: str
    enabled: bool = True
    config: Dict = field(default_factory=dict)
    dependencies: List[str] = field(default_factory=list)


@dataclass
class SuperpowersConfig:
    """Configuration for superpowers integration"""
    # Skills from superpowers
    brainstorming_enabled: bool = True
    writing_plans_enabled: bool = True
    executing_plans_enabled: bool = True
    subagent_driven_dev_enabled: bool = True
    test_driven_dev_enabled: bool = True
    systematic_debugging_enabled: bool = True
    verification_enabled: bool = True
    code_review_enabled: bool = True
    git_worktrees_enabled: bool = True

    # Hooks from oh-my-opencode
    atlas_enabled: bool = True
    claude_code_hooks_enabled: bool = True
    ralph_loop_enabled: bool = True
    todo_enforcer_enabled: bool = True

    # Agents from oh-my-opencode
    sisyphus_enabled: bool = True
    oracle_enabled: bool = True
    librarian_enabled: bool = True
    explore_enabled: bool = True
    prometheus_enabled: bool = True

    # MCPs from oh-my-opencode
    websearch_enabled: bool = True
    context7_enabled: bool = True
    grep_app_enabled: bool = True

    # Contains-studio agents
    contains_studio_enabled: bool = True
    auto_delegate_enabled: bool = True
    proactive_agents_enabled: bool = True


class SuperpowersIntegration:
    """
    Main integration class for all superpowers features

    Manages:
    - Dynamic loading of skills from superpowers
    - Dynamic loading of hooks from oh-my-opencode
    - Dynamic loading of agents from both projects
    - MCP configuration and management
    - Command registration
    - Tool integration
    """

    def __init__(self, config: Optional[SuperpowersConfig] = None):
        """Initialize the integration"""
        self.config = config or SuperpowersConfig()
        self.modules: Dict[str, IntegrationModule] = {}
        self.skill_hooks: Dict[str, List[Callable]] = {}
        self.hook_registry: Dict[str, Callable] = {}

        # Paths
        self.ralph_dir = Path.home() / '.claude' / 'skills' / 'ralph'
        self.superpowers_dir = self.ralph_dir / 'superpowers'
        self.oh_my_opencode_dir = self.ralph_dir / 'oh-my-opencode'
        self.contains_studio_dir = Path.home() / '.claude' / 'agents'

        logger.info("Superpowers Integration initialized")

    def install_all(self) -> Dict[str, Any]:
        """
        Install and integrate all features

        Returns:
            Installation summary
        """
        summary = {
            'skills': [],
            'hooks': [],
            'agents': [],
            'mcps': [],
            'commands': [],
            'errors': []
        }

        try:
            # 1. Install superpowers skills
            if self.config.brainstorming_enabled:
                self._install_superpowers_skills(summary)

            # 2. Install oh-my-opencode hooks
            if self.config.atlas_enabled:
                self._install_oh_my_opencode_hooks(summary)

            # 3. Install agents
            if self.config.sisyphus_enabled or self.config.contains_studio_enabled:
                self._install_agents(summary)

            # 4. Install MCPs
            if self.config.websearch_enabled:
                self._install_mcps(summary)

            # 5. Register commands
            self._register_commands(summary)

            # 6. Create configuration files
            self._create_config_files()

            logger.info(f"Installation complete: {summary}")
            return summary

        except Exception as e:
            logger.error(f"Installation failed: {e}")
            summary['errors'].append(str(e))
            return summary

    def _install_superpowers_skills(self, summary: Dict):
        """Install skills from superpowers"""
        logger.info("Installing superpowers skills...")

        skills_dir = self.superpowers_dir / 'skills'
        skills_dir.mkdir(parents=True, exist_ok=True)

        # Define skills to install
        skills = [
            'brainstorming',
            'writing-plans',
            'executing-plans',
            'subagent-driven-development',
            'test-driven-development',
            'systematic-debugging',
            'verification-before-completion',
            'requesting-code-review',
            'receiving-code-review',
            'using-git-worktrees',
            'finishing-a-development-branch',
            'dispatching-parallel-agents',
            'using-superpowers',
            'writing-skills'
        ]

        for skill in skills:
            try:
                # Copy skill from superpowers source
                source = Path('/tmp/superpowers/skills') / skill
                if source.exists():
                    dest = skills_dir / skill
                    if dest.exists():
                        shutil.rmtree(dest)
                    shutil.copytree(source, dest)

                    module = IntegrationModule(
                        name=skill,
                        type=IntegrationType.SKILL,
                        source='superpowers',
                        path=str(dest),
                        enabled=True
                    )

                    self.modules[skill] = module
                    summary['skills'].append(skill)

                    logger.info(f"  ✓ Installed skill: {skill}")

            except Exception as e:
                logger.warning(f"  ✗ Failed to install skill {skill}: {e}")
                summary['errors'].append(f"skill:{skill} - {e}")

    def _install_oh_my_opencode_hooks(self, summary: Dict):
        """Install hooks from oh-my-opencode"""
        logger.info("Installing oh-my-opencode hooks...")

        hooks_dir = self.oh_my_opencode_dir / 'hooks'
        hooks_dir.mkdir(parents=True, exist_ok=True)

        # Key hooks to install
        hooks = [
            'atlas',              # Main orchestrator
            'claude-code-hooks',   # Claude Code compatibility
            'ralph-loop',         # Autonomous iteration
            'todo-continuation-enforcer',  # Task completion
            'thinking-block-validator',  # Validate thinking
            'session-recovery',   # Recovery from errors
            'edit-error-recovery',  # Recovery from edit errors
            'start-work',         # Work initialization
        ]

        for hook in hooks:
            try:
                source = Path('/tmp/oh-my-opencode/src/hooks') / hook
                if source.exists():
                    dest = hooks_dir / hook
                    if dest.exists():
                        shutil.rmtree(dest)
                    shutil.copytree(source, dest)

                    module = IntegrationModule(
                        name=hook,
                        type=IntegrationType.HOOK,
                        source='oh-my-opencode',
                        path=str(dest),
                        enabled=True
                    )

                    self.modules[hook] = module
                    summary['hooks'].append(hook)

                    logger.info(f"  ✓ Installed hook: {hook}")

            except Exception as e:
                logger.warning(f"  ✗ Failed to install hook {hook}: {e}")
                summary['errors'].append(f"hook:{hook} - {e}")

    def _install_agents(self, summary: Dict):
        """Install agents from both projects"""
        logger.info("Installing agents...")

        # oh-my-opencode agents
        if self.config.sisyphus_enabled:
            omo_agents_dir = self.oh_my_opencode_dir / 'agents'
            omo_agents_dir.mkdir(parents=True, exist_ok=True)

            agents = [
                'sisyphus',
                'oracle',
                'librarian',
                'explore',
                'prometheus'
            ]

            for agent in agents:
                try:
                    source = Path('/tmp/oh-my-opencode/src/agents') / f"{agent}.ts"
                    if source.exists():
                        dest = omo_agents_dir / f"{agent}.md"
                        # Convert TypeScript agent to Markdown format for Claude Code
                        self._convert_agent_to_md(source, dest)

                        module = IntegrationModule(
                            name=agent,
                            type=IntegrationType.AGENT,
                            source='oh-my-opencode',
                            path=str(dest),
                            enabled=True
                        )

                        self.modules[agent] = module
                        summary['agents'].append(agent)

                        logger.info(f"  ✓ Installed agent: {agent}")

                except Exception as e:
                    logger.warning(f"  ✗ Failed to install agent {agent}: {e}")
                    summary['errors'].append(f"agent:{agent} - {e}")

        # contains-studio agents (already handled by contains-studio integration)
        if self.config.contains_studio_enabled:
            summary['agents'].append('contains-studio-agents (30+ agents)')
            logger.info(f"  ✓ Contains-studio agents already integrated")

    def _install_mcps(self, summary: Dict):
        """Install MCPs from oh-my-opencode"""
        logger.info("Installing MCPs...")

        mcps_dir = self.oh_my_opencode_dir / 'mcps'
        mcps_dir.mkdir(parents=True, exist_ok=True)

        mcps = [
            'websearch',
            'context7',
            'grep_app'
        ]

        for mcp in mcps:
            try:
                source = Path('/tmp/oh-my-opencode/src/mcp') / f"{mcp}.ts"
                if source.exists():
                    dest = mcps_dir / f"{mcp}.json"

                    # Create MCP config
                    mcp_config = self._create_mcp_config(mcp, source)
                    with open(dest, 'w') as f:
                        json.dump(mcp_config, f, indent=2)

                    module = IntegrationModule(
                        name=mcp,
                        type=IntegrationType.MCP,
                        source='oh-my-opencode',
                        path=str(dest),
                        enabled=True
                    )

                    self.modules[mcp] = module
                    summary['mcps'].append(mcp)

                    logger.info(f"  ✓ Installed MCP: {mcp}")

            except Exception as e:
                logger.warning(f"  ✗ Failed to install MCP {mcp}: {e}")
                summary['errors'].append(f"mcp:{mcp} - {e}")

    def _register_commands(self, summary: Dict):
        """Register commands from both projects"""
        logger.info("Registering commands...")

        commands_dir = Path.home() / '.claude' / 'commands'

        # Ralph sub-commands
        ralph_commands = [
            ('brainstorm', 'Interactive design refinement'),
            ('write-plan', 'Create implementation plan'),
            ('execute-plan', 'Execute plan in batches'),
            ('debug', 'Systematic debugging'),
            ('review', 'Code review'),
            ('status', 'Show Ralph status'),
            ('list-agents', 'List all available agents'),
            ('list-skills', 'List all available skills')
        ]

        for cmd_name, description in ralph_commands:
            try:
                cmd_file = commands_dir / f'ralph-{cmd_name}.md'

                content = f"""---
description: "{description}"
disable-model-invocation: true
---

Invoke ralph:{cmd_name} via the ralph skill
"""

                with open(cmd_file, 'w') as f:
                    f.write(content)

                summary['commands'].append(f'ralph-{cmd_name}')
                logger.info(f"  ✓ Registered command: /ralph-{cmd_name}")

            except Exception as e:
                logger.warning(f"  ✗ Failed to register command {cmd_name}: {e}")
                summary['errors'].append(f"command:{cmd_name} - {e}")

    def _create_config_files(self):
        """Create configuration files"""
        logger.info("Creating configuration files...")

        config_dir = Path.home() / '.claude' / 'config'
        config_dir.mkdir(parents=True, exist_ok=True)

        # Main Ralph config
        config_file = config_dir / 'ralph.json'

        config = {
            'superpowers': {
                'enabled': True,
                'skills': {
                    'brainstorming': self.config.brainstorming_enabled,
                    'writing-plans': self.config.writing_plans_enabled,
                    'executing-plans': self.config.executing_plans_enabled,
                    'subagent-driven-development': self.config.subagent_driven_dev_enabled,
                    'test-driven-development': self.config.test_driven_dev_enabled,
                    'systematic-debugging': self.config.systematic_debugging_enabled,
                    'verification-before-completion': self.config.verification_enabled,
                    'requesting-code-review': self.config.code_review_enabled,
                    'receiving-code-review': self.config.code_review_enabled,
                    'using-git-worktrees': self.config.git_worktrees_enabled,
                    'finishing-a-development-branch': True,
                    'dispatching-parallel-agents': True
                },
                'hooks': {
                    'atlas': self.config.atlas_enabled,
                    'claude-code-hooks': self.config.claude_code_hooks_enabled,
                    'ralph-loop': self.config.ralph_loop_enabled,
                    'todo-continuation-enforcer': self.config.todo_enforcer_enabled
                },
                'agents': {
                    'sisyphus': self.config.sisyphus_enabled,
                    'oracle': self.config.oracle_enabled,
                    'librarian': self.config.librarian_enabled,
                    'explore': self.config.explore_enabled,
                    'prometheus': self.config.prometheus_enabled,
                    'contains-studio': self.config.contains_studio_enabled
                },
                'mcps': {
                    'websearch': self.config.websearch_enabled,
                    'context7': self.config.context7_enabled,
                    'grep_app': self.config.grep_app_enabled
                },
                'auto_delegate': self.config.auto_delegate_enabled,
                'proactive_agents': self.config.proactive_agents_enabled
            },
            'multi_agent': {
                'enabled': os.getenv('RALPH_MULTI_AGENT', '').lower() == 'true',
                'max_workers': int(os.getenv('RALPH_MAX_WORKERS', 12)),
                'min_workers': int(os.getenv('RALPH_MIN_WORKERS', 2))
            }
        }

        with open(config_file, 'w') as f:
            json.dump(config, f, indent=2)

        logger.info(f"  ✓ Created config: {config_file}")

    def _convert_agent_to_md(self, source_ts: Path, dest_md: Path):
        """Convert TypeScript agent to Markdown format for Claude Code"""
        # Read TypeScript source
        with open(source_ts, 'r') as f:
            content = f.read()

        # Extract key information
        # This is a simplified conversion - real implementation would parse TS properly

        md_content = f"""---
name: {source_ts.stem}
description: "Agent from oh-my-opencode: {source_ts.stem}"
color: blue
tools: Read, Write, Edit, Bash, Grep, Glob
---

# {source_ts.stem.title()} Agent

This agent was imported from oh-my-opencode.

## Purpose

{self._extract_purpose(content)}

## Capabilities

- Multi-model orchestration
- Specialized tool usage
- Background task management
- Advanced code analysis

## Integration

This agent integrates with Ralph's multi-agent system for coordinated task execution.
"""

        with open(dest_md, 'w') as f:
            f.write(md_content)

    def _extract_purpose(self, ts_content: str) -> str:
        """Extract purpose description from TypeScript content"""
        # Simplified extraction
        if 'orchestrat' in ts_content.lower():
            return "Orchestrates multiple agents and coordinates complex workflows"
        elif 'oracle' in ts_content.lower() or 'consult' in ts_content.lower():
            return "Provides consultation and debugging expertise"
        elif 'librarian' in ts_content.lower() or 'docs' in ts_content.lower():
            return "Searches documentation and codebases"
        elif 'explore' in ts_content.lower() or 'grep' in ts_content.lower():
            return "Fast codebase exploration and search"
        elif 'prometheus' in ts_content.lower() or 'plan' in ts_content.lower():
            return "Strategic planning and task breakdown"
        else:
            return "Specialized AI agent for specific tasks"

    def _create_mcp_config(self, mcp_name: str, source_file: Path) -> Dict:
        """Create MCP configuration"""
        # Base MCP config
        configs = {
            'websearch': {
                'name': 'websearch',
                'command': 'npx',
                'args': ['-y', '@modelcontextprotocol/server-exa'],
                'env': {
                    'EXA_API_KEY': '${EXA_API_KEY}'
                }
            },
            'context7': {
                'name': 'context7',
                'command': 'npx',
                'args': ['-y', '@context7/mcp-server-docs'],
                'env': {}
            },
            'grep_app': {
                'name': 'grep_app',
                'command': 'npx',
                'args': ['-y', '@modelcontextprotocol/server-github'],
                'env': {
                    'GITHUB_TOKEN': '${GITHUB_TOKEN}'
                }
            }
        }

        return configs.get(mcp_name, {
            'name': mcp_name,
            'command': 'echo',
            'args': ['MCP not configured']
        })

    def load_skill(self, skill_name: str) -> Optional[Any]:
        """Dynamically load a skill"""
        skill_key = f"skills.{skill_name}"
        if skill_key not in self.modules:
            logger.warning(f"Skill not found: {skill_name}")
            return None

        module = self.modules[skill_key]

        try:
            # Load the skill module
            spec = importlib.util.spec_from_file_location(
                f"ralph.skills.{skill_name}",
                os.path.join(module.path, 'SKILL.md')
            )

            if spec and spec.loader:
                skill_module = importlib.util.module_from_spec(spec)
                spec.loader.exec_module(skill_module)
                return skill_module

        except Exception as e:
            logger.error(f"Failed to load skill {skill_name}: {e}")

        return None

    def invoke_hook(self, hook_name: str, context: Dict) -> Any:
        """Invoke a registered hook"""
        if hook_name not in self.hook_registry:
            logger.debug(f"Hook not registered: {hook_name}")
            return None

        try:
            hook_func = self.hook_registry[hook_name]
            return hook_func(context)
        except Exception as e:
            logger.error(f"Hook {hook_name} failed: {e}")
            return None

    def register_hook(self, hook_name: str, hook_func: Callable):
        """Register a hook function"""
        self.hook_registry[hook_name] = hook_func
        logger.info(f"Registered hook: {hook_name}")

    def get_status(self) -> Dict:
        """Get integration status"""
        return {
            'modules': {
                name: {
                    'type': module.type.value,
                    'source': module.source,
                    'enabled': module.enabled,
                    'path': module.path
                }
                for name, module in self.modules.items()
            },
            'config': {
                'superpowers': {
                    'skills_enabled': sum(1 for m in self.modules.values()
                                        if m.type == IntegrationType.SKILL and m.enabled),
                    'hooks_enabled': sum(1 for m in self.modules.values()
                                       if m.type == IntegrationType.HOOK and m.enabled),
                    'agents_enabled': sum(1 for m in self.modules.values()
                                        if m.type == IntegrationType.AGENT and m.enabled),
                    'mcps_enabled': sum(1 for m in self.modules.values()
                                      if m.type == IntegrationType.MCP and m.enabled)
                }
            },
            'hooks_registered': list(self.hook_registry.keys())
        }


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

    parser = argparse.ArgumentParser(description='Ralph Superpowers Integration')
    parser.add_argument('--install', action='store_true', help='Install all superpowers')
    parser.add_argument('--status', action='store_true', help='Show integration status')
    parser.add_argument('--config', help='Path to config file')

    args = parser.parse_args()

    # Load config
    config = SuperpowersConfig()
    if args.config:
        with open(args.config) as f:
            config_data = json.load(f)
            # Apply config...

    # Create integration
    integration = SuperpowersIntegration(config)

    if args.install:
        summary = integration.install_all()
        print("\n=== Installation Summary ===")
        print(f"Skills: {len(summary['skills'])}")
        print(f"Hooks: {len(summary['hooks'])}")
        print(f"Agents: {len(summary['agents'])}")
        print(f"MCPs: {len(summary['mcps'])}")
        print(f"Commands: {len(summary['commands'])}")
        if summary['errors']:
            print(f"\nErrors: {len(summary['errors'])}")
            for error in summary['errors']:
                print(f"  - {error}")

    elif args.status:
        status = integration.get_status()
        print(json.dumps(status, indent=2))


if __name__ == '__main__':
    main()
