import sys
import json
import re
import argparse
from pathlib import Path
from typing import Dict, Any

# --- Template Definition ---
AGENT_TEMPLATE = """---
name: {name}
description: {description}
mode: subagent
model: {model}
temperature: {temperature}
max_tokens: {max_tokens}
tools:
{tools_yaml}
---

# {title}

<system-reminder>
{system_reminder}
</system-reminder>

## Memory Integration

**At Session Start:**

1. Read `memory.md` to check for prior context
2. Review `development-guidelines.md` for established patterns
3. Check `architecture-decisions.md` to understand existing design context

**During Work:**

- Reference `memory.md` to avoid duplicating previous work
- Build on previous findings rather than starting from scratch
- Check `blockers.md` for known dead ends

**After Work:**

- Update `memory.md` with key findings and insights
- Log important discoveries in `architecture-decisions.md`
- Document dead ends in `blockers.md`

## Core Pattern

{core_pattern}

## Capabilities

{capabilities}

## Tool Strategy

{tool_strategy}

## Output Format

{output_format}
"""

# --- Core Logic ---

def sanitize_name(name: str) -> str:
    """
    Sanitize agent name to ensure it's safe for file paths.
    Allowed: lowercase alphanumeric and dashes.
    """
    name = name.lower().strip()
    if not re.match(r'^[a-z0-9-]+$', name):
        raise ValueError(f"Invalid agent name '{name}'. Must match ^[a-z0-9-]+$")
    return name

def validate_tools(tools: Dict[str, bool]) -> str:
    """
    Convert tools dict to YAML format and validate.
    """
    yaml_lines = []
    for tool, enabled in tools.items():
        yaml_lines.append(f"  {tool}: {str(enabled).lower()}")
    return "\n".join(yaml_lines)

def build_agent(config: Dict[str, Any]) -> str:
    """
    Build and write the agent configuration file.
    """
    # 1. Extract and Sanitize
    name = sanitize_name(config.get('name', 'unnamed-agent'))
    
    # 2. Path Validation
    # Use the standard OpenCodeKit agent directory
    base_dir = Path.home() / ".config/opencode/agent"
    
    # Fallback for local testing if global config doesn't exist
    if not base_dir.exists():
        base_dir = Path(".opencode/agent") # Project local
        if not base_dir.exists():
             base_dir.mkdir(parents=True, exist_ok=True)

    target_file = (base_dir / f"{name}.md").resolve()
    
    # Strict path check
    if not str(target_file).startswith(str(base_dir.resolve())):
        raise ValueError(f"Path traversal attempt detected: {target_file}")
    
    if target_file.exists() and not config.get('force', False):
        raise FileExistsError(f"Agent '{name}' already exists at {target_file}")

    # 3. Prepare Data
    tools_yaml = validate_tools(config.get('tools', {}))
    
    data = {
        'name': name,
        'description': config.get('description', 'Custom agent'),
        'model': config.get('model', 'github-copilot/claude-haiku-4.5'),
        'temperature': config.get('temperature', 0.3),
        'max_tokens': config.get('max_tokens', 5000),
        'tools_yaml': tools_yaml,
        'title': config.get('title', f"{name.replace('-', ' ').title()} Agent"),
        'system_reminder': config.get('system_reminder', 'No system reminder provided.'),
        'core_pattern': config.get('core_pattern', 'No core pattern defined.'),
        'capabilities': config.get('capabilities', '- No specific capabilities defined.'),
        'tool_strategy': config.get('tool_strategy', 'No tool strategy defined.'),
        'output_format': config.get('output_format', 'No specific output format defined.')
    }

    # 4. Render
    content = AGENT_TEMPLATE.format(**data)

    # 5. Write
    target_file.write_text(content)
    return str(target_file)

def main():
    parser = argparse.ArgumentParser(description="Generate OpenCodeKit agent configuration")
    parser.add_argument("config", help="JSON configuration string")
    args = parser.parse_args()

    try:
        config = json.loads(args.config)
        path = build_agent(config)
        print(f"SUCCESS: Agent created at {path}")
    except Exception as e:
        print(f"ERROR: {str(e)}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
