"""Generate and write task-specific CLAUDE.md files into agent worktrees.

Before an agent starts, this module writes a CLAUDE.md file at the worktree
root containing:
- Task instructions and goals
- Role constraints and behavioural rules
- Allowed file paths (scope guard)
- Context file links (.sdd/project.md, etc.)

Claude Code automatically reads CLAUDE.md from the project root, so this
gives each agent a tailored set of instructions without modifying the
shared repository's CLAUDE.md.
"""

from __future__ import annotations

import logging
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from pathlib import Path

    from bernstein.core.models import Task

logger = logging.getLogger(__name__)


def generate_claude_md(
    tasks: list[Task],
    *,
    session_id: str,
    role: str,
    workdir: Path,
    context_files: list[str] | None = None,
    extra_instructions: str = "",
) -> str:
    """Generate CLAUDE.md content for a task-specific worktree.

    Args:
        tasks: Tasks assigned to this agent.
        session_id: Agent session identifier.
        role: Agent role (backend, qa, security, etc.).
        workdir: Project working directory (for resolving context files).
        context_files: Additional context files the agent should read.
        extra_instructions: Extra instructions to append.

    Returns:
        Complete CLAUDE.md content string.
    """
    sections: list[str] = []

    # Header
    sections.append(f"# Bernstein Agent: {role} ({session_id})")
    sections.append("")
    sections.append("This file was auto-generated by Bernstein for this agent session.")
    sections.append("It provides task-specific instructions and constraints.")
    sections.append("")

    # Role constraints
    sections.append("## Role constraints")
    sections.append(f"You are a **{role}** agent. Stay within your role's scope.")
    _role_rules = _get_role_rules(role)
    if _role_rules:
        for rule in _role_rules:
            sections.append(f"- {rule}")
    sections.append("")

    # Task instructions
    sections.append("## Assigned tasks")
    for i, task in enumerate(tasks, 1):
        sections.append(f"### Task {i}: {task.title} (id={task.id})")
        sections.append(f"**Priority:** {task.priority} | **Scope:** {task.scope.value}")
        sections.append("")
        sections.append(task.description)
        sections.append("")

    # Allowed file paths
    all_owned: list[str] = []
    for task in tasks:
        all_owned.extend(task.owned_files)
    if all_owned:
        sections.append("## Allowed file paths")
        sections.append("You should focus your work on these files:")
        for fp in sorted(set(all_owned)):
            sections.append(f"- `{fp}`")
        sections.append("")
        sections.append(
            "If you need to create new files, keep them within the directories "
            "of your allowed paths. Do not modify files outside your scope "
            "unless strictly necessary for your task."
        )
        sections.append("")

    # Context file links
    effective_context_files = context_files or []
    # Always include project.md if it exists
    project_md = workdir / ".sdd" / "project.md"
    if project_md.exists() and ".sdd/project.md" not in effective_context_files:
        effective_context_files = [".sdd/project.md", *effective_context_files]

    if effective_context_files:
        sections.append("## Context files")
        sections.append("Read these files for project context:")
        for cf in effective_context_files:
            sections.append(f"- `{cf}`")
        sections.append("")

    # Git safety
    sections.append("## Git rules")
    sections.append(f"- Work on branch `agent/{session_id}` only.")
    sections.append("- NEVER force-push or skip git hooks.")
    sections.append("- NEVER commit secrets, API keys, or credentials.")
    sections.append("- Review changes with `git diff` before committing.")
    sections.append("")

    # Extra instructions
    if extra_instructions:
        sections.append("## Additional instructions")
        sections.append(extra_instructions)
        sections.append("")

    return "\n".join(sections)


def write_claude_md(
    worktree_path: Path,
    tasks: list[Task],
    *,
    session_id: str,
    role: str,
    workdir: Path,
    context_files: list[str] | None = None,
    extra_instructions: str = "",
) -> Path:
    """Write a task-specific CLAUDE.md to the worktree root.

    Args:
        worktree_path: Root of the agent's git worktree.
        tasks: Tasks assigned to this agent.
        session_id: Agent session identifier.
        role: Agent role.
        workdir: Project working directory.
        context_files: Additional context files.
        extra_instructions: Extra instructions.

    Returns:
        Path to the written CLAUDE.md file.
    """
    content = generate_claude_md(
        tasks,
        session_id=session_id,
        role=role,
        workdir=workdir,
        context_files=context_files,
        extra_instructions=extra_instructions,
    )

    claude_md_path = worktree_path / "CLAUDE.md"
    try:
        claude_md_path.write_text(content, encoding="utf-8")
        logger.info("Wrote task-specific CLAUDE.md to %s (%d bytes)", claude_md_path, len(content))
    except OSError as exc:
        logger.warning("Failed to write CLAUDE.md to %s: %s", claude_md_path, exc)

    return claude_md_path


def _get_role_rules(role: str) -> list[str]:
    """Return behavioural rules specific to each role.

    Args:
        role: Agent role name (lowercase).

    Returns:
        List of rule strings for the role.
    """
    rules: dict[str, list[str]] = {
        "backend": [
            "Focus on implementation, APIs, and data models.",
            "Write tests for new functionality.",
            "Follow existing code patterns and conventions.",
        ],
        "qa": [
            "Read and analyse code; do NOT create new source files.",
            "Run tests and report failures with file paths and line numbers.",
            "Use only read-only tools: Bash, Read, Grep, Glob.",
        ],
        "security": [
            "Audit code for security vulnerabilities.",
            "Do NOT modify source files directly.",
            "Report findings with severity, file path, and remediation advice.",
        ],
        "docs": [
            "Update documentation and docstrings.",
            "Do NOT change application logic or test files.",
            "Use clear, concise language.",
        ],
        "frontend": [
            "Focus on UI components, styles, and user interaction.",
            "Test visual changes when possible.",
            "Follow the project's design system and conventions.",
        ],
        "manager": [
            "Decompose work into tasks and assign to specialist agents.",
            "Do NOT implement code directly.",
            "Coordinate between agents via the task server.",
        ],
        "reviewer": [
            "Review code changes for correctness and style.",
            "Do NOT modify files directly.",
            "Provide specific, actionable feedback.",
        ],
    }
    return rules.get(role.lower(), [])
