"""Lesson 5: Dotfiles in ONA."""

from __future__ import annotations

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


class DotfilesLesson(BaseLesson):
    """Teaches creating a dotfiles repo, install scripts, and linking to ONA."""

    @classmethod
    def meta(cls) -> LessonMeta:
        return LessonMeta(
            id="dotfiles",
            number=5,
            title="Dotfiles",
            description="Personalize your ONA environment with a dotfiles repository.",
            overview="Create a dotfiles repo on GitLab, write an install script, link it to ONA, "
            "and learn best practices for non-interactive setup.",
        )

    def steps(self) -> list[LessonStep]:
        return [
            LessonStep(
                title="What Are Dotfiles?",
                explanation=(
                    "**Dotfiles** are configuration files (like `.bashrc`, `.gitconfig`, "
                    "`.vimrc`) that personalize your shell and tools. They're called 'dotfiles' "
                    "because they start with a dot.\n\n"
                    "In ONA, you can maintain a GitLab repository with your dotfiles. ONA will "
                    "clone and apply them automatically to every new environment."
                ),
                why=(
                    "Dotfiles ensure your terminal aliases, Git config, and editor preferences "
                    "are consistent across all ONA environments. Set them up once, use them "
                    "everywhere."
                ),
            ),
            LessonStep(
                title="Creating a Dotfiles Repository",
                explanation=(
                    "Create a new repository on GitLab to store your dotfiles:\n\n"
                    "1. Go to `https://gitlab.example.com` and create a new project\n"
                    "2. Name it `dotfiles` (convention)\n"
                    "3. Add your configuration files and an install script\n\n"
                    "The repository structure should look like:"
                ),
                code=CodeBlock(
                    language="bash",
                    source=(
                        "dotfiles/\n"
                        "├── install.sh      # Install script (auto-detected)\n"
                        "├── .bashrc         # Shell configuration\n"
                        "├── .gitconfig      # Git configuration\n"
                        "└── .vimrc          # Editor configuration (optional)"
                    ),
                ),
            ),
            LessonStep(
                title="The Install Script",
                explanation=(
                    "ONA looks for an install script in this priority order:\n\n"
                    "1. `install.sh`\n"
                    "2. `bootstrap.sh`\n"
                    "3. `setup.sh`\n\n"
                    "The script **must be non-interactive** — no prompts or user input. "
                    "It runs automatically during environment creation."
                ),
                code=CodeBlock(
                    language="bash",
                    source=(
                        "#!/usr/bin/env bash\n"
                        "set -euo pipefail\n"
                        "\n"
                        'DOTFILES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"\n'
                        "\n"
                        'echo "Installing dotfiles from $DOTFILES_DIR..."\n'
                        "\n"
                        "for file in .bashrc .gitconfig; do\n"
                        '    if [ -f "$DOTFILES_DIR/$file" ]; then\n'
                        '        ln -sf "$DOTFILES_DIR/$file" "$HOME/$file"\n'
                        '        echo "  Linked $file"\n'
                        "    fi\n"
                        "done\n"
                        "\n"
                        'echo "Dotfiles installation complete!"'
                    ),
                    filename="install.sh",
                ),
                why=(
                    "Using symbolic links (`ln -sf`) is preferred over copying. This way, if "
                    "you update your dotfiles repo and rebuild, the changes are reflected "
                    "immediately without re-running the install script."
                ),
            ),
            LessonStep(
                title="Initialize and Push Your Dotfiles Repo",
                explanation=(
                    "After scaffolding, copy the sample dotfiles into your `dotfiles` repo, "
                    "make the install script executable, and push to GitLab."
                ),
                code=CodeBlock(
                    language="bash",
                    source=(
                        "# From your dotfiles repo\n"
                        "cp -R /path/to/cde-onboard-practice/lesson-05-dotfiles/dotfiles/. ./\n"
                        "chmod +x install.sh\n"
                        "git init\n"
                        "git add .\n"
                        "git commit -m \"Add initial dotfiles\"\n"
                        "git remote add origin https://gitlab.example.com/your-user/dotfiles.git\n"
                        "git push -u origin main"
                    ),
                ),
            ),
            LessonStep(
                title="Linking Dotfiles to ONA",
                explanation=(
                    "Tell ONA where your dotfiles repository is (after pushing it to GitLab):"
                ),
                code=CodeBlock(
                    language="bash",
                    source=(
                        "# Set your dotfiles repository\n"
                        "gitpod user dotfiles set \\\n"
                        "  --repository https://gitlab.example.com/your-user/dotfiles.git\n"
                        "\n"
                        "# To apply changes, rebuild your environment:\n"
                        "gitpod environment devcontainer rebuild"
                    ),
                ),
                deep_dive=(
                    "ONA clones your dotfiles to `~/dotfiles` in the environment. The install "
                    "script is then executed from that directory.\n\n"
                    "Each user has **one** dotfiles repository. It's applied to all environments "
                    "created by that user.\n\n"
                    "If you need to test changes to your install script, use "
                    "`gitpod environment devcontainer rebuild` to rebuild the current environment "
                    "with the latest version."
                ),
            ),
            LessonStep(
                title="Best Practices",
                explanation=(
                    "Tips for effective dotfiles:\n\n"
                    "- Keep the install script **non-interactive** (no `read` or `select`)\n"
                    "- Use `set -euo pipefail` for safety\n"
                    "- Check if files exist before linking (`if [ -f ... ]`)\n"
                    "- Use `ln -sf` (force) to overwrite existing files\n"
                    "- Don't include secrets in your dotfiles repo\n"
                    "- Test your install script locally before pushing\n\n"
                    "Click **Scaffold & Complete** to create a sample dotfiles directory."
                ),
            ),
        ]

    def scaffold_files(self) -> list[ScaffoldFile]:
        return [
            ScaffoldFile(
                relative_path="dotfiles/install.sh",
                template_name="dotfiles_install.sh",
                description="Non-interactive install script that symlinks dotfiles.",
            ),
            ScaffoldFile(
                relative_path="dotfiles/.bashrc",
                template_name="dotfiles_bashrc",
                description="Sample .bashrc with aliases and prompt customization.",
            ),
            ScaffoldFile(
                relative_path="dotfiles/.gitconfig",
                template_name="dotfiles_gitconfig",
                description="Sample .gitconfig with useful aliases and defaults.",
            ),
        ]
