"""SEF Agents Generator.

Generates AGENTS.md with SEF protocol and mandatory fix workflow.

Usage:
    from sef_agents.tools.agents_generator import generate_agents_file
    result = generate_agents_file("/path/to/project")
"""

from pathlib import Path

import structlog

logger = structlog.get_logger(__name__)


AGENTS_MD_CONTENT = """# AI Coding Assistant Protocol — SEF v2.1

> This file is read by Cursor, Windsurf, Antigravity, and GitHub Copilot at session start.
> It is the always-on context layer. Rules here are non-negotiable and apply to every task.

---

## Non-Negotiable: SEF-Agents Entry Point

If `sef-agents` MCP is enabled and available, **ALL tasks run via a SEF agent**.
Direct code edits that bypass agent roles are prohibited.

**Before any task:**
1. Call `agent(action="list")` to confirm MCP is active.
2. Call `agent(action="activate", name="<role>")` to set the agent.
3. Proceed only after activation confirmed.

If MCP is unavailable, apply the rules in this file manually and note the deviation.

---

## Communication Protocol (Non-Negotiable)

BE LACONIC. Every sentence ≤ 15 words. Active voice. Technical vocabulary only.

| Rule | Target |
|---|---|
| Sentence length | 15–20 words max |
| Prose style | Active voice. "Service scales." Not "Scaling is handled by." |
| Forbidden phrases | "It is important to note", "In order to", "As discussed", "Here is the code" |
| Output format | Tables and bullets over paragraphs. Code over explanation. |

---

## Agent Registry

### SDLC Agents — Standard Flow

| Agent | Activate With | Primary Duty | Escalates To |
|---|---|---|---|
| `discovery` | `agent(action="activate", name="discovery")` | Scan codebase, generate `codemap/`, `FEATURES.md`, `AGENTS.md` | User |
| `product_manager` | `agent(action="activate", name="product_manager")` | Define `REQ.md` with testable AC, story dependencies, flow context | User |
| `qa_lead` | `agent(action="activate", name="qa_lead")` | Validate AC: testable, automatable, edge cases covered | PM + Architect |
| `architect` | `agent(action="activate", name="architect")` | System design, `CODE_MAP.md` update, regression risk check | PM + User |
| `developer` | `agent(action="activate", name="developer")` | Implement per Elite Quality Protocol. Log debt. Do not fix debt without approval. | Architect + PM |
| `pr_reviewer` | `agent(action="activate", name="pr_reviewer")` | Compliance check: types, logging, exceptions, tests, debt logging | Developer + Architect |
| `tester` | `agent(action="activate", name="tester")` | Write real-execution tests from AC. No mocking the unit under test. | PM + QA Lead |
| `security_owner` | `agent(action="activate", name="security_owner")` | Vulnerability audit: input validation, auth/authz, secrets | Developer + User |
| `scrum_master` | `agent(action="activate", name="scrum_master")` | Update `REQ.md` → Done, write `handoff_log.jsonl`, generate `project_status.md` | User |
| `test_designer` | `agent(action="activate", name="test_designer")` | Design test strategy and conceptual cases from AC | QA Lead + PM |

### Utility Agents — On-Demand

| Agent | Activate With | When to Use |
|---|---|---|
| `forensic_engineer` | `agent(action="activate", name="forensic_engineer")` | Any bug, incident, or unexpected behavior. Always before `developer` on fixes. |
| `strategist` | `agent(action="activate", name="strategist")` | Design decisions with multiple viable approaches. Trade-off analysis. |
| `platform_engineer` | `agent(action="activate", name="platform_engineer")` | Codebase health scans, CI/CD, DevEx issues. |

---

## Mandatory Fix Workflow

**A fix is any change addressing a defect, regression, or unexpected behavior.**
New features are NOT fixes.

```
1. forensic_engineer  →  Root cause analysis (RCA). Output: sef-reports/post-mortem-*.md
2. strategist         →  Solution design, trade-off analysis. Output: recommendation
3. developer          →  Implementation + tests
```

Skipping `forensic_engineer` on a fix is blocked at PR review. No exceptions.

---

## SDLC Phase Sequence

```
Phase 0: Discovery       →  discovery
Phase 1: Requirements    →  product_manager
Phase 2: QA Gate         →  qa_lead (parallel: test_designer)
Phase 3: Design          →  architect
Phase 4: Implementation  →  developer
Phase 5: Review          →  pr_reviewer (background: security_owner)
Phase 6: Verification    →  tester + security_owner (parallel, both must pass)
Phase 7: Completion      →  scrum_master
```

Parallel phases require `workflow(action="parallel_start", story_id="...")` before proceeding.
Both parallel agents must pass before the phase advances.

---

## Escalation Protocol

Apply at every decision point where a blocker exists.

```
L1 — Auto-resolve:  Route to the responsible agent. Example: design unclear → architect.
L2 — Collaborate:   Bring in related agents. Example: architect + PM together.
L3 — HALT:          Stop. Ask the user. Call log(event="escalation", level="L3", ...) first.
```

L3 is mandatory when:
- Regression risk cannot be scoped without user input
- Debt fix discovered mid-feature (user decides: fix now or log only)
- Critical vulnerability found (always HALT, no exception)
- AC is not testable after L1+L2 attempts

---

## Debt Guardrail (Critical)

When debt is found during feature work:

1. Call `log(event="debt", debt_type="...", severity="...", location="...")`.
2. HALT. Ask the user: fix now or log for later?
3. User says fix: update status to `Approved`, fix in same PR or new `DEBT-XXX` story.
4. User says log: continue with feature. Status stays `Open`.

**Agents do NOT decide on their own.** Silent debt fixes are scope creep.

---

## Tool Reference (SEF-Agents MCP)

### Primary Tools — Call These First

| Tool | When to Call |
|---|---|
| `agent(action="list")` | Session start. Confirm MCP active. |
| `agent(action="activate", name="<role>")` | Before any SDLC task. |
| `set_project_root(path="...")` | First call in any new project session. |
| `set_story_context(story_id="...")` | At start of each story. |
| `workflow(action="init", story_id="...")` | When starting a new story. |
| `workflow(action="state", story_id="...")` | To check current phase and blockers. |
| `workflow(action="next", story_id="...")` | After completing any phase. |

### Logging — Call on Every State Change

| Event | Call |
|---|---|
| Escalation | `log(event="escalation", level="L1|L2|L3", reason="...", to_agents="...")` |
| Ownership transfer | `log(event="ownership", to_owner="...", reason="...")` |
| Phase complete | `log(event="phase", phase="...", outcome="passed|failed", next_phase="...")` |
| Debt found | `log(event="debt", debt_type="...", severity="...", location="...")` |
| Replan triggered | `log(event="replan", trigger="...", impact="...")` |
| Artifact done | `log(event="artifact", artifact="...")` |

### Analysis — Use scan() for all codebase reads

```
scan(target="health", directory="...")       — Full health report. Run at project start.
scan(target="debt", directory="...")         — Technical debt registry.
scan(target="security", directory="...")     — Vulnerability audit.
scan(target="compliance", file_path="...")   — SEF quality check on a file.
scan(target="complexity", files="...")       — Cyclomatic/cognitive complexity.
```

---

## Elite Code Quality Protocol (Non-Negotiable)

### Python
- 100% type hints on all function signatures.
- `structlog` only. `print()` is forbidden in production.
- Derive all exceptions from `AppError`.
- Google-style docstrings. No AI fluff in docstrings.
- `ruff check --fix && ruff format && pyright` must exit 0.

### TypeScript
- `any` is forbidden. Use explicit `interface` or `type`.
- `Zod` schema required for all external inputs.
- `TanStack Query` for all server-side state.

### Universal
- Cyclomatic complexity ≤ 15 per function.
- Test coverage ≥ 85% on changed files.
- No mocking the unit under test (UUT). Only mock external third-party APIs.
- Paste actual shell execution output in the PR compliance section.

---

## Artifacts

| Artifact | Owner | Location |
|---|---|---|
| `codemap/CODE_MAP.md` | Discovery, Architect | `codemap/` |
| `REQ.md` | Product Manager | `docs/requirements/` |
| `TECH_DEBT.md` | Discovery, PR Reviewer | `docs/` |
| `handoff_log.jsonl` | Scrum Master | Project root |
| `project_status.md` | Scrum Master | `docs/` |
| `FEATURES.md` | Discovery | Project root |
| `EXTERNAL_DEPS.md` | Discovery, Architect | `docs/` |
| `sef-reports/` | Platform Engineer, Security | `sef-reports/` |

---

*Generated by SEF Discovery Agent. Regenerate with `generate_agents_md(directory=".")` after major protocol changes.*
"""


def generate_agents_file(directory: str) -> str:
    """Generate AGENTS.md at project root.

    Args:
        directory: Path to project root.

    Returns:
        Status message.
    """
    root = Path(directory)

    if not root.exists():
        return f"Error: Directory {directory} does not exist."

    agents_path = root / "AGENTS.md"

    # Always overwrite - this is a protocol file
    agents_path.write_text(AGENTS_MD_CONTENT, encoding="utf-8")

    logger.info("agents_md_generated", path=str(agents_path))

    return f"✅ AGENTS.md generated at `{agents_path}`"
