"""SPOQ project initialization command.

Bootstraps a project directory with SPOQ structure, templates, and
optional MCP configuration. Replaces the shell-based spoq-init.sh
for users who install SPOQ via pip/PyPI.

Skills are bundled as package data in data/skills/ and copied during
init. To update bundled skills, sync from .claude/skills/ in the
source repository.
"""

import json
import shutil
from datetime import datetime, timezone
from pathlib import Path


# =============================================================================
# Package data location — bundled skills shipped with the wheel
# =============================================================================

_PACKAGE_DIR = Path(__file__).resolve().parent
_BUNDLED_SKILLS_DIR = _PACKAGE_DIR / "data" / "skills"

# Core skills always installed
CORE_SKILLS = [
    "epic-planning",
    "epic-validation",
    "task-validation",
    "agent-execution",
    "team-execution",
    "agent-validation",
    "journal-tracker",
    "skill-maker",
    "lib",
]


# =============================================================================
# Templates — CLAUDE.md, journal.md, ROADMAP.yml, epics README
# =============================================================================

CLAUDE_MD_TEMPLATE = """\
# Project Guidelines

## SPOQ Methodology

This project uses [SPOQ](https://spoqpaper.com) (Specialist Orchestrated Queuing) for multi-agent development.

### Common Commands

```bash
# Plan an epic
/epic-planning "Feature description"

# Validate an epic
/epic-validation @spoq/epics/active/epic-name

# Execute an epic
/agent-execution @spoq/epics/active/epic-name

# Execute with agent teams (persona-specialized)
/team-execution @spoq/epics/active/epic-name

# Validate completed work
/agent-validation

# Plan a multi-epic program
/epic-planning --map "Program name"
```

### Validation Thresholds

- **Planning**: 95 avg / 90 min
- **Code**: 95 avg / 80 min

### Repository Structure

- `.claude/skills/` - SPOQ skill definitions
- `code/` - Application source code
- `documents/` - Documentation
- `spoq/epics/` - Epic and task definitions
- `spoq/maps/` - Multi-epic program maps
- `infrastructure/` - Docker and Terraform configs
- `tests/` - Integration and end-to-end tests
- `journal.md` - Development journal
- `TODO.yml` - Time-boxed task tracker

### MCP Server

The SPOQ MCP server provides tools for epic, map, and task management.
Configure in `.mcp.json`:

```json
{
  "mcpServers": {
    "spoq": {
      "command": "spoq",
      "args": ["mcp"]
    }
  }
}
```

### Workflow

1. **Plan** — `/epic-planning` decomposes goals into atomic tasks
2. **Validate** — `/epic-validation` scores against 10 quality metrics
3. **Execute** — `/agent-execution` dispatches parallel agent swarms
4. **Verify** — `/agent-validation` scores delivered code

### Git Operations

- NEVER create commits automatically - user handles git
- Update journal.md when completing significant work
"""

JOURNAL_MD_TEMPLATE = """\
# Development Journal

This journal tracks all AI agent work sessions with timestamps, confidence scores, and detailed summaries.

## Journal Format

Each entry includes:
- **Agent**: Name of AI assistant
- **Timestamps**: Start/end times (UTC)
- **Confidence**: 0.0-1.0 quality score
- **Session Type**: Category of work (development, refactor, bugfix, planning, etc.)
- **Files Modified**: List of changed files

---

"""

def _roadmap_yml_content() -> str:
    """Generate a fresh ROADMAP.yml with the current UTC timestamp."""
    ts = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
    return f"""\
version: 1
updated_at: "{ts}"
epics: []
"""


ROADMAP_YML_TEMPLATE = _roadmap_yml_content

TODO_YML_TEMPLATE = """\
version: "1"
updated: "<timestamp>"

sections: []

standalone: []

maps: []
"""

EPICS_README_TEMPLATE = """\
# Epic Definitions

This directory contains SPOQ epic definitions.

## Structure

Each epic is a directory containing:
```
epic-name/
├── EPIC.md         # Epic overview, architecture, waves
└── tasks/          # Task YAML files
    ├── 01-task.yml
    ├── 02-task.yml
    └── ...
```

## Creating an Epic

```bash
/epic-planning "Your feature description"
```

## Running an Epic

```bash
# Validate first
/epic-validation @spoq/epics/active/your-epic

# Then execute
/agent-execution @spoq/epics/active/your-epic
```

## Examples

See `example-config-validator/` for a complete working example.
"""


# =============================================================================
# 5-Category Directory Structure
# =============================================================================

# Directories created for every init (fresh or upgrade)
DIRECTORIES = [
    ".claude/skills",
    "code",
    "documents",
    "infrastructure/docker",
    "infrastructure/terraform",
    "spoq/epics/active",
    "spoq/epics/backlog",
    "spoq/epics/complete",
    "spoq/maps/active",
    "spoq/maps/backlog",
    "spoq/maps/complete",
    "tests",
]


# =============================================================================
# Public API
# =============================================================================

def run_init(
    target: str = ".",
    full: bool = False,
    with_mcp: bool = False,
    upgrade: bool = False,
) -> None:
    """Bootstrap or upgrade SPOQ in the target directory."""
    target_path = Path(target).resolve()

    if not target_path.exists():
        target_path.mkdir(parents=True)
        print(f"Created directory: {target_path}")

    if upgrade:
        _upgrade(target_path)
    else:
        _fresh_init(target_path, full=full)

    if with_mcp:
        _setup_mcp(target_path)

    print(f"\nSPOQ initialized in: {target_path}")
    print("\nNext steps:")
    print("  1. Open the project in Claude Code")
    print("  2. Run /epic-planning to plan your first epic")
    print("  3. Run /epic-validation to verify quality")
    print("  4. Run /agent-execution to dispatch agent swarms")


# =============================================================================
# Fresh init
# =============================================================================

def _fresh_init(target: Path, full: bool = False) -> None:
    """Create fresh SPOQ project structure."""
    # Directory structure (5-category model)
    for d in DIRECTORIES:
        (target / d).mkdir(parents=True, exist_ok=True)

    # CLAUDE.md
    claude_md = target / "CLAUDE.md"
    if not claude_md.exists():
        claude_md.write_text(encoding="utf-8", data=CLAUDE_MD_TEMPLATE)
        print("  Created CLAUDE.md")
    else:
        print("  CLAUDE.md already exists (skipped)")

    # journal.md
    journal = target / "journal.md"
    if not journal.exists():
        journal.write_text(encoding="utf-8", data=JOURNAL_MD_TEMPLATE)
        print("  Created journal.md")

    # ROADMAP.yml
    roadmap = target / "spoq" / "ROADMAP.yml"
    if not roadmap.exists():
        roadmap.write_text(encoding="utf-8", data=ROADMAP_YML_TEMPLATE())
        print("  Created spoq/ROADMAP.yml")

    # TODO.yml
    todo_yml = target / "TODO.yml"
    if not todo_yml.exists():
        todo_yml.write_text(encoding="utf-8", data=TODO_YML_TEMPLATE)
        print("  Created TODO.yml")

    # spoq/epics/README.md
    epics_readme = target / "spoq" / "epics" / "README.md"
    if not epics_readme.exists():
        epics_readme.write_text(encoding="utf-8", data=EPICS_README_TEMPLATE)
        print("  Created spoq/epics/README.md")

    # Full skills from bundled package data
    _install_skills(target)

    # Example epic (if --full)
    if full:
        _create_example_epic(target)

    print(f"  Created {len(DIRECTORIES)} directories")


# =============================================================================
# Skills installation — copies bundled package data
# =============================================================================

def _install_skills(target: Path) -> None:
    """Copy full skill definitions from bundled package data."""
    skills_dir = target / ".claude" / "skills"
    copied = 0
    skipped = 0

    if not _BUNDLED_SKILLS_DIR.is_dir():
        print("  WARNING: Bundled skills not found, creating stubs instead")
        _create_skill_stubs_fallback(target)
        return

    for skill_name in CORE_SKILLS:
        src = _BUNDLED_SKILLS_DIR / skill_name
        dst = skills_dir / skill_name

        if not src.is_dir():
            continue

        if dst.exists():
            # Check if existing skill is a stub (< 50 lines in SKILL.md)
            skill_md = dst / "SKILL.md"
            if skill_md.exists():
                line_count = len(skill_md.read_text(encoding="utf-8").splitlines())
                if line_count >= 50:
                    skipped += 1
                    continue
            # Overwrite stubs with full skills
            shutil.rmtree(dst)

        shutil.copytree(
            src, dst,
            ignore=shutil.ignore_patterns("__pycache__", "*.pyc"),
        )
        copied += 1

    if copied:
        print(f"  Installed {copied} skills (full definitions)")
    if skipped:
        print(f"  Skipped {skipped} skills (already present)")


def _create_skill_stubs_fallback(target: Path) -> None:
    """Fallback: create minimal skill stubs when package data is missing.

    This path should only be reached in development or broken installs.
    """
    _STUB_DESCRIPTIONS = {
        "epic-planning": "Decompose high-level goals into structured epics with atomic tasks, dependency DAGs, and wave-based phases. Use when planning new features, migrations, or complex initiatives in spoq/epics/.",
        "epic-validation": "Validate EPIC.md files and task sets with 10 planning-focused metrics (0-100). Use after epic planning and before agent-execution. Pass threshold 95+.",
        "agent-execution": "Orchestrate parallel sub-agent swarms on automation epics. Use when running /agent-execution @spoq/epics/epic-name to execute multi-task epics with Opus workers and Sonnet QA.",
        "agent-validation": "Validate sub-agent work against task definitions with 10-metric scoring (0-100). Use after Opus completes work and code compiles. Invokes Sonnet sub-agent for review. Pass threshold 95+.",
        "team-execution": "Orchestrate wave-based agent teams with persona-specialized workers. Use when running /team-execution @spoq/epics/epic-name to execute multi-task epics with Agent Teams, inter-agent messaging, and context-preserving rework.",
        "task-validation": "Validate task YAML definitions before execution with 10 planning-focused metrics (0-100). Use after task creation and before agent-execution. Pass threshold 95+.",
        "journal-tracker": "Track AI agent work sessions in journal.md with timestamps, confidence scores, and detailed summaries. Supports auto-archiving, database parsing, and XAI/meta-orchestration integration.",
        "skill-maker": "Create new Claude Code skills following Anthropic best practices. Use when you need to create a new skill for a specific domain or workflow that doesn't exist yet.",
    }

    skills_dir = target / ".claude" / "skills"
    created = 0

    for skill_name, description in _STUB_DESCRIPTIONS.items():
        skill_dir = skills_dir / skill_name
        skill_file = skill_dir / "SKILL.md"

        if skill_file.exists():
            continue

        skill_dir.mkdir(parents=True, exist_ok=True)
        title = skill_name.replace("-", " ").title()
        content = f"---\nname: {skill_name}\ndescription: {description}\n---\n\n# {title}\n\nThis is a stub. Install the full SPOQ package for complete skill definitions.\n"
        skill_file.write_text(encoding="utf-8", data=content)
        created += 1

    if created:
        print(f"  Created {created} skill stubs (install spoq package for full skills)")


# =============================================================================
# Example epic
# =============================================================================

def _create_example_epic(target: Path) -> None:
    """Create the example config-validator epic."""
    epic_dir = target / "spoq" / "epics" / "active" / "example-config-validator"
    if epic_dir.exists():
        print("  Example epic already exists (skipped)")
        return

    tasks_dir = epic_dir / "tasks"
    tasks_dir.mkdir(parents=True, exist_ok=True)

    # EPIC.md
    (epic_dir / "EPIC.md").write_text(encoding="utf-8", data="""\
# Epic: Example Config Validator

## Overview

A minimal example epic demonstrating SPOQ structure. Build a configuration
validator with a parser, API, and test suite across 3 execution waves.

## Architecture

```
Parser -> API -> Tests
```

## Success Criteria

- [ ] Parser handles YAML input
- [ ] API returns structured JSON
- [ ] Tests cover the full pipeline
- [ ] All tasks have three-point estimates
- [ ] Dependency graph is acyclic

## Task Dependencies

```
Wave 0: 01-parser, 02-models (parallel)
Wave 1: 03-api (depends on 01, 02)
Wave 2: 04-tests (depends on 03)
```

## Dispatch Strategy

**Wave 0:** Tasks 01, 02 (parallel foundation)
**Wave 1:** Task 03 (API, depends on Wave 0)
**Wave 2:** Task 04 (tests, depends on Wave 1)

## Estimated Effort

| Wave | Tasks | Duration |
|------|-------|----------|
| 0 | 2 | ~1.5h |
| 1 | 1 | ~2h |
| 2 | 1 | ~1.5h |
| **Total** | **4** | **~5h** |
""")

    # Task YAMLs
    tasks = [
        ("01-parser.yml", "01-parser", "Config Parser", 0, "critical", "[]"),
        ("02-models.yml", "02-models", "Data Models", 0, "high", "[]"),
        ("03-api.yml", "03-api", "REST API", 1, "high", "[01-parser, 02-models]"),
        ("04-tests.yml", "04-tests", "Integration Tests", 2, "medium", "[03-api]"),
    ]

    for filename, tid, title, phase, priority, deps in tasks:
        (tasks_dir / filename).write_text(encoding="utf-8", data=f"""\
id: {tid}
title: {title}
epic: example-config-validator
status: pending
priority: {priority}
phase: {phase}

estimate:
  optimistic: 30m
  realistic: 1h
  pessimistic: 2h

dependencies: {deps}

skills_required:
  - python

files_to_touch:
  - src/{tid.split('-')[1]}.py

acceptance_criteria:
  - "[ ] Implementation complete"
  - "[ ] Tests pass"

description: |
  ## Objective
  Implement the {title.lower()} component.

  ## Steps
  1. Create the module
  2. Add core logic
  3. Write tests

  ## Verification
  Run pytest to verify.
""")

    print("  Created example epic: example-config-validator (4 tasks)")


# =============================================================================
# Upgrade
# =============================================================================

def _upgrade(target: Path) -> None:
    """Upgrade an existing SPOQ installation."""
    upgraded = []

    # Ensure full directory structure (5-category model)
    for d in DIRECTORIES:
        path = target / d
        if not path.exists():
            path.mkdir(parents=True)
            upgraded.append(f"Created {d}/")

    # Migrate legacy structures
    legacy_automation = target / "automation" / "tasks"
    if legacy_automation.exists():
        dest = target / "spoq" / "epics" / "active"
        for item in legacy_automation.iterdir():
            if item.is_dir():
                target_dest = dest / item.name
                if not target_dest.exists():
                    shutil.move(str(item), str(target_dest))
                    upgraded.append(f"Migrated automation/tasks/{item.name} -> spoq/epics/active/")
        print("  Migrated legacy automation/tasks/ structure")

    legacy_factory = target / "factory" / "epics"
    if legacy_factory.exists():
        dest = target / "spoq" / "epics"
        for item in legacy_factory.iterdir():
            if item.is_dir():
                target_dest = dest / "active" / item.name
                if not target_dest.exists():
                    shutil.move(str(item), str(target_dest))
                    upgraded.append(f"Migrated factory/epics/{item.name} -> spoq/epics/active/")
        print("  Migrated legacy factory/ structure")

    # Install full skills (replaces stubs with complete definitions)
    _install_skills(target)

    # Ensure ROADMAP.yml (auto-migrate from ROADMAP.md if needed)
    roadmap_yml = target / "spoq" / "ROADMAP.yml"
    roadmap_md = target / "spoq" / "ROADMAP.md"
    if not roadmap_yml.exists():
        roadmap_yml.write_text(encoding="utf-8", data=ROADMAP_YML_TEMPLATE())
        upgraded.append("Created spoq/ROADMAP.yml")
        if roadmap_md.exists():
            print("  NOTICE: spoq/ROADMAP.md detected — created spoq/ROADMAP.yml as the new machine-readable roadmap.")
            print("          Review and remove spoq/ROADMAP.md once migration is confirmed.")

    # Ensure TODO.yml
    todo_yml = target / "TODO.yml"
    if not todo_yml.exists():
        todo_yml.write_text(encoding="utf-8", data=TODO_YML_TEMPLATE)
        upgraded.append("Created TODO.yml")

    # Ensure epics README
    epics_readme = target / "spoq" / "epics" / "README.md"
    if not epics_readme.exists():
        epics_readme.write_text(encoding="utf-8", data=EPICS_README_TEMPLATE)
        upgraded.append("Created spoq/epics/README.md")

    if upgraded:
        print(f"  Upgraded {len(upgraded)} items")
    else:
        print("  Already up to date")


# =============================================================================
# MCP configuration
# =============================================================================

def _setup_mcp(target: Path) -> None:
    """Configure .mcp.json for the SPOQ MCP server."""
    mcp_file = target / ".mcp.json"

    mcp_config = {
        "mcpServers": {
            "spoq": {
                "command": "spoq",
                "args": ["mcp"],
            }
        }
    }

    if mcp_file.exists():
        existing = json.loads(mcp_file.read_text(encoding="utf-8"))
        servers = existing.get("mcpServers", {})
        if "spoq" not in servers:
            servers["spoq"] = mcp_config["mcpServers"]["spoq"]
            existing["mcpServers"] = servers
            mcp_file.write_text(encoding="utf-8", data=json.dumps(existing, indent=2) + "\n")
            print("  Added spoq entry to existing .mcp.json")
        else:
            print("  .mcp.json already has spoq entry (skipped)")
    else:
        mcp_file.write_text(encoding="utf-8", data=json.dumps(mcp_config, indent=2) + "\n")
        print("  Created .mcp.json")
