"""
File system helpers for initialization.
"""

from __future__ import annotations

import subprocess
import json
from pathlib import Path
import yaml

from kanbus.config import DEFAULT_CONFIGURATION
from kanbus.project_management_template import (
    DEFAULT_PROJECT_MANAGEMENT_TEMPLATE,
    DEFAULT_PROJECT_MANAGEMENT_TEMPLATE_FILENAME,
)
from kanbus.project import ensure_project_local_directory


class InitializationError(RuntimeError):
    """Raised when project initialization fails."""


def ensure_git_repository(root: Path) -> None:
    """Ensure the provided path is inside a git repository.

    :param root: Directory to check for a git repository.
    :type root: Path
    :raises InitializationError: If the path is not a git repository.
    """
    result = subprocess.run(
        ["git", "rev-parse", "--is-inside-work-tree"],
        cwd=root,
        capture_output=True,
        text=True,
        check=False,
    )
    if result.returncode != 0 or result.stdout.strip() != "true":
        raise InitializationError("not a git repository")


def initialize_project(root: Path, create_local: bool = False) -> None:
    """Initialize the Kanbus project directory structure.

    :param root: Repository root path.
    :type root: Path
    :param create_local: Whether to create a project-local directory.
    :type create_local: bool
    :raises InitializationError: If the project is already initialized.
    """
    project_dir = root / "project"
    if project_dir.exists():
        raise InitializationError("already initialized")

    issues_dir = project_dir / "issues"

    project_dir.mkdir(parents=True, exist_ok=False)
    issues_dir.mkdir(parents=True)
    config_path = root / ".kanbus.yml"
    if not config_path.exists():
        config_path.write_text(
            yaml.safe_dump(DEFAULT_CONFIGURATION, sort_keys=False),
            encoding="utf-8",
        )
    _write_project_guard_files(project_dir)
    _write_tool_block_files(root)
    template_path = root / DEFAULT_PROJECT_MANAGEMENT_TEMPLATE_FILENAME
    if not template_path.exists():
        template_path.write_text(
            DEFAULT_PROJECT_MANAGEMENT_TEMPLATE,
            encoding="utf-8",
        )
    if create_local:
        ensure_project_local_directory(project_dir)


def _write_project_guard_files(project_dir: Path) -> None:
    agents_path = project_dir / "AGENTS.md"
    agents_path.write_text(
        "\n".join(
            [
                "# DO NOT EDIT HERE",
                "",
                "Editing anything under project/ directly is hacking the data and is a sin against The Way.",
                "Do not read or write in this folder. Do not inspect issue JSON with tools like cat or jq. Use Kanbus commands instead.",
                "",
                "See ../AGENTS.md and ../CONTRIBUTING_AGENT.md for required process.",
            ]
        )
        + "\n",
        encoding="utf-8",
    )
    do_not_edit = project_dir / "DO_NOT_EDIT"
    do_not_edit.write_text(
        "\n".join(
            [
                "DO NOT EDIT ANYTHING IN project/",
                "This folder is guarded by The Way.",
                "Do not inspect issue JSON with tools like cat or jq.",
                "All changes must go through Kanbus (see ../AGENTS.md and ../CONTRIBUTING_AGENT.md).",
            ]
        )
        + "\n",
        encoding="utf-8",
    )


def _write_tool_block_files(root: Path) -> None:
    cursorignore = root / ".cursorignore"
    if not cursorignore.exists():
        cursorignore.write_text("project/\n", encoding="utf-8")

    claude_dir = root / ".claude"
    claude_dir.mkdir(parents=True, exist_ok=True)
    claude_settings = claude_dir / "settings.json"
    if not claude_settings.exists():
        claude_settings.write_text(
            json.dumps(
                {
                    "permissions": {
                        "deny": [
                            "Read(./project/**)",
                            "Edit(./project/**)",
                        ]
                    }
                },
                indent=2,
            )
            + "\n",
            encoding="utf-8",
        )

    vscode_dir = root / ".vscode"
    vscode_dir.mkdir(parents=True, exist_ok=True)
    vscode_settings = vscode_dir / "settings.json"
    if not vscode_settings.exists():
        vscode_settings.write_text(
            json.dumps(
                {
                    "files.exclude": {"**/project/**": True},
                    "files.watcherExclude": {"**/project/**": True},
                    "search.exclude": {"**/project/**": True},
                },
                indent=2,
            )
            + "\n",
            encoding="utf-8",
        )
