"""Lesson 6: Managing Multiple Repositories in ONA."""

from __future__ import annotations

from cde_onboard.lessons.base import BaseLesson
from cde_onboard.models import CodeBlock, LessonMeta, LessonStep, ScaffoldFile


class MultiRepoLesson(BaseLesson):
    """Teaches multi-repo setups with devcontainer cloning and tasks."""

    @classmethod
    def meta(cls) -> LessonMeta:
        return LessonMeta(
            id="multi-repo",
            number=6,
            title="Managing Multiple Repos",
            description="Work with multiple repositories in a single ONA environment.",
            overview="Clone multiple repos using devcontainer.json or tasks, organize them "
            "under /workspaces/, and configure VS Code multi-root workspaces.",
        )

    def steps(self) -> list[LessonStep]:
        return [
            LessonStep(
                title="Why Multi-Repo?",
                explanation=(
                    "Many projects span multiple repositories — a frontend, a backend API, "
                    "shared libraries, and infrastructure configs. ONA lets you work with all "
                    "of them in a single environment.\n\n"
                    "There are two approaches to set this up:\n\n"
                    "1. **onCreateCommand** in `devcontainer.json` (recommended)\n"
                    "2. **Tasks** in `.ona/automations.yaml`"
                ),
            ),
            LessonStep(
                title="Approach 1: onCreateCommand (Recommended)",
                explanation=(
                    "Use the **object form** of `onCreateCommand` in `devcontainer.json` to "
                    "clone multiple repos in parallel. Each key runs as a separate parallel "
                    "process."
                ),
                code=CodeBlock(
                    language="json",
                    source=(
                        '{\n'
                        '  "onCreateCommand": {\n'
                        '    "clone-frontend": "git clone https://gitlab.example.com/team/frontend.git /workspaces/frontend",\n'
                        '    "clone-api": "git clone https://gitlab.example.com/team/api.git /workspaces/api",\n'
                        '    "clone-shared": "git clone https://gitlab.example.com/team/shared-lib.git /workspaces/shared-lib"\n'
                        '  }\n'
                        '}'
                    ),
                    filename="devcontainer.json",
                ),
                why=(
                    "The object form of `onCreateCommand` runs all commands **in parallel**. "
                    "This is much faster than cloning repos sequentially. Each key is a label, "
                    "and each value is the command to run."
                ),
            ),
            LessonStep(
                title="Approach 2: Tasks in Automations",
                explanation=(
                    "Alternatively, you can use tasks in `.ona/automations.yaml` for more "
                    "control over cloning logic — like conditional cloning or post-clone setup."
                ),
                code=CodeBlock(
                    language="yaml",
                    source=(
                        "tasks:\n"
                        "  clone-frontend:\n"
                        "    name: Clone Frontend\n"
                        "    command: |\n"
                        "      if [ ! -d /workspaces/frontend ]; then\n"
                        "        git clone https://gitlab.example.com/team/frontend.git /workspaces/frontend\n"
                        "      fi\n"
                        "    triggeredBy:\n"
                        "      - postDevcontainerStart\n"
                        "\n"
                        "  clone-api:\n"
                        "    name: Clone API\n"
                        "    command: |\n"
                        "      if [ ! -d /workspaces/api ]; then\n"
                        "        git clone https://gitlab.example.com/team/api.git /workspaces/api\n"
                        "      fi\n"
                        "    triggeredBy:\n"
                        "      - postDevcontainerStart"
                    ),
                    filename=".ona/automations.yaml",
                ),
                deep_dive=(
                    "Tasks give you more flexibility than `onCreateCommand`:\n\n"
                    "- **Conditional cloning**: Only clone if the directory doesn't exist\n"
                    "- **Post-clone setup**: Add `dependsOn` to run `npm install` after cloning\n"
                    "- **Manual trigger**: Allow on-demand cloning of optional repos\n\n"
                    "The trade-off is that tasks run sequentially by default (unless they have "
                    "no dependencies between them)."
                ),
            ),
            LessonStep(
                title="Workspace Convention",
                explanation=(
                    "Always clone additional repositories to `/workspaces/<repo-name>`. This "
                    "is the ONA convention and keeps all code in a consistent location."
                ),
                code=CodeBlock(
                    language="bash",
                    source=(
                        "# Standard workspace layout:\n"
                        "/workspaces/\n"
                        "├── my-project/        # Primary repo (auto-cloned by ONA)\n"
                        "├── frontend/          # Cloned by onCreateCommand\n"
                        "├── api/               # Cloned by onCreateCommand\n"
                        "└── shared-lib/        # Cloned by onCreateCommand"
                    ),
                ),
            ),
            LessonStep(
                title="VS Code Multi-Root Workspaces",
                explanation=(
                    "With multiple repos, you can use VS Code's multi-root workspace feature "
                    "to see all repositories in a single editor window. Create a "
                    "`.code-workspace` file:"
                ),
                code=CodeBlock(
                    language="json",
                    source=(
                        '{\n'
                        '  "folders": [\n'
                        '    { "path": "/workspaces/frontend", "name": "Frontend" },\n'
                        '    { "path": "/workspaces/api", "name": "API" },\n'
                        '    { "path": "/workspaces/shared-lib", "name": "Shared Library" }\n'
                        '  ],\n'
                        '  "settings": {\n'
                        '    "editor.formatOnSave": true\n'
                        '  }\n'
                        '}'
                    ),
                    filename="my-project.code-workspace",
                ),
            ),
            LessonStep(
                title="Complete Multi-Repo Setup",
                explanation=(
                    "Here's a full devcontainer.json for a multi-repo environment. "
                    "Click **Scaffold & Complete** to create this file."
                ),
                code=CodeBlock(
                    language="json",
                    source=(
                        '{\n'
                        '  "name": "Multi-Repo ONA Environment",\n'
                        '  "image": "mcr.microsoft.com/devcontainers/base:ubuntu",\n'
                        '  "features": {\n'
                        '    "ghcr.io/devcontainers/features/node:1": { "version": "20" },\n'
                        '    "ghcr.io/devcontainers/features/python:1": { "version": "3.11" }\n'
                        '  },\n'
                        '  "onCreateCommand": {\n'
                        '    "clone-frontend": "git clone https://gitlab.example.com/team/frontend.git /workspaces/frontend",\n'
                        '    "clone-api": "git clone https://gitlab.example.com/team/api.git /workspaces/api"\n'
                        '  },\n'
                        '  "postCreateCommand": "cd /workspaces/frontend && npm install"\n'
                        '}'
                    ),
                    filename=".devcontainer/devcontainer.json",
                ),
            ),
            LessonStep(
                title="Testing & Verification",
                explanation=(
                    "Before pushing, verify your multi-repo configuration:\n\n"
                    "**1. Validate Repository URLs**"
                ),
                code=CodeBlock(
                    language="bash",
                    source=(
                        "# Test that repository URLs are accessible\n"
                        "git ls-remote https://gitlab.example.com/team/frontend.git\n"
                        "git ls-remote https://gitlab.example.com/team/api.git\n"
                        "# Should list refs if accessible"
                    ),
                ),
                deep_dive=(
                    "**2. Validate JSON Syntax**\n\n"
                    "```bash\n"
                    "cat .devcontainer/devcontainer.json | jq .\n"
                    "# Should output formatted JSON if valid\n"
                    "```\n\n"
                    "**3. Test in ONA Environment**\n\n"
                    "After pushing and creating a new environment:\n"
                    "```bash\n"
                    "# Verify all repos were cloned\n"
                    "ls /workspaces/\n"
                    "# Should show: your-primary-repo, frontend, api, etc.\n"
                    "\n"
                    "# Check each repo is a valid git repository\n"
                    "git -C /workspaces/frontend status\n"
                    "git -C /workspaces/api status\n"
                    "\n"
                    "# Verify branches and commits\n"
                    "git -C /workspaces/frontend branch\n"
                    "git -C /workspaces/api log --oneline -5\n"
                    "```\n\n"
                    "**Expected Success Indicators:**\n"
                    "- ✓ All repositories cloned to /workspaces/\n"
                    "- ✓ Each repo is in a valid Git state\n"
                    "- ✓ VS Code workspace shows all folders\n"
                    "- ✓ You can switch between repos in the editor\n\n"
                    "**Common Issues:**\n"
                    "- Clone fails → Check repository URLs are correct and accessible\n"
                    "- Permission denied → Ensure GitLab OAuth is configured\n"
                    "- Parallel clone conflicts → Check onCreateCommand object syntax\n"
                    "- Wrong branch cloned → Specify branch in git clone command"
                ),
            ),
            LessonStep(
                title="Apply to Your Repository",
                explanation=(
                    "Scaffolding writes the multi-repo `devcontainer.json` under "
                    "`./cde-onboard-practice/lesson-06-multi-repo/`. "
                    "Copy the `.devcontainer` folder into your repo and commit."
                ),
                code=CodeBlock(
                    language="bash",
                    source=(
                        "# From your repo root\n"
                        "cp -R cde-onboard-practice/lesson-06-multi-repo/.devcontainer ./\n"
                        "git add .devcontainer/devcontainer.json\n"
                        "git commit -m \"Add multi-repo devcontainer\"\n"
                        "git push"
                    ),
                ),
            ),
        ]

    def scaffold_files(self) -> list[ScaffoldFile]:
        return [
            ScaffoldFile(
                relative_path=".devcontainer/devcontainer.json",
                template_name="devcontainer_multi_repo.json",
                description="Multi-repo devcontainer.json with parallel cloning via onCreateCommand.",
            ),
        ]
