"""TaskService.create appends the project's baseline constraints (flag-gated)."""

from __future__ import annotations

from typing import TYPE_CHECKING
from uuid import UUID, uuid4

from roboco.config import settings
from roboco.db.tables import AgentTable, ProjectTable
from roboco.models import AgentRole, AgentStatus, Complexity, Team
from roboco.models.base import TaskNature
from roboco.models.task import TaskCreateRequest, TaskType
from roboco.services.task import TaskService

if TYPE_CHECKING:
    import pytest
    from sqlalchemy.ext.asyncio import AsyncSession


async def _seed(db: AsyncSession) -> tuple[AgentTable, ProjectTable]:
    agent = AgentTable(
        id=uuid4(),
        name="Dev",
        slug=f"be-dev-{uuid4().hex[:8]}",
        role=AgentRole.DEVELOPER,
        team=Team.BACKEND,
        status=AgentStatus.ACTIVE,
        model_config={},
        system_prompt="dev",
        capabilities=[],
        permissions={},
        metrics={},
    )
    db.add(agent)
    await db.flush()
    project = ProjectTable(
        id=uuid4(),
        name="C-Proj",
        slug=f"c-proj-{uuid4().hex[:8]}",
        git_url="https://example.com/r.git",
        assigned_cell=Team.BACKEND,
        created_by=agent.id,
    )
    db.add(project)
    await db.flush()
    return agent, project


def _req(
    agent: AgentTable, project: ProjectTable, description: str
) -> TaskCreateRequest:
    return TaskCreateRequest(
        title="A task",
        description=description,
        acceptance_criteria=["it works"],
        team=Team.BACKEND,
        created_by=UUID(str(agent.id)),
        task_type=TaskType.CODE,
        nature=TaskNature.TECHNICAL,
        estimated_complexity=Complexity.MEDIUM,
        project_id=UUID(str(project.id)),
    )


async def test_baseline_attached_when_flag_on(
    db_session: AsyncSession, monkeypatch: pytest.MonkeyPatch
) -> None:
    monkeypatch.setattr(settings, "conventions_enabled", True)
    agent, project = await _seed(db_session)
    task = await TaskService(db_session).create(_req(agent, project, "Do the work"))
    # The conventions block lives in `constraints`, not `description` (the
    # 2026-07-07 fix: description is the human-authored instruction only).
    assert task.description == "Do the work"
    assert task.constraints is not None
    assert "## Constraints" in task.constraints
    assert "no lint suppressions" in task.constraints


async def test_flag_off_attaches_nothing(
    db_session: AsyncSession, monkeypatch: pytest.MonkeyPatch
) -> None:
    monkeypatch.setattr(settings, "conventions_enabled", False)
    agent, project = await _seed(db_session)
    task = await TaskService(db_session).create(_req(agent, project, "Do the work"))
    assert task.description == "Do the work"
    assert task.constraints is None


async def test_baseline_not_suppressed_by_agent_constraints_section(
    db_session: AsyncSession, monkeypatch: pytest.MonkeyPatch
) -> None:
    # An agent-authored ## Constraints section in the description must NOT
    # suppress the mandatory server baseline — the description keeps the
    # agent's block and `constraints` carries the server baseline (separate
    # field, so neither suppresses the other).
    monkeypatch.setattr(settings, "conventions_enabled", True)
    agent, project = await _seed(db_session)
    seeded = "Do the work\n\n## Constraints\n- a task-specific note"
    task = await TaskService(db_session).create(_req(agent, project, seeded))
    assert task.description is not None
    assert "a task-specific note" in task.description
    assert task.constraints is not None
    assert "no lint suppressions" in task.constraints


async def test_baseline_attach_is_idempotent(
    db_session: AsyncSession, monkeypatch: pytest.MonkeyPatch
) -> None:
    monkeypatch.setattr(settings, "conventions_enabled", True)
    agent, project = await _seed(db_session)
    svc = TaskService(db_session)
    task = await svc.create(_req(agent, project, "Do the work"))
    before = task.constraints
    await svc._attach_baseline_constraints(task)
    assert task.constraints == before
    assert task.constraints is not None
    assert task.constraints.count("no lint suppressions") == 1
