"""TDD tests for the tdd_recommended heuristic.

The heuristic classifies tasks as TDD-friendly based on enriched context
signals — no LLM call needed, pure function on task data.
"""

from __future__ import annotations

import pytest

from loom.skills.tdd import classify_tdd_recommendation


# ---------------------------------------------------------------------------
# Positive signals — TDD recommended
# ---------------------------------------------------------------------------


class TestTDDRecommended:
    """Tasks where TDD should be recommended."""

    def test_store_crud_function(self):
        """Store-level CRUD tasks are prime TDD candidates."""
        result = classify_tdd_recommendation(
            title="Add create_issue and list_issues to store.py",
            context={"files": ["loom/graph/store.py"], "description": "CRUD functions for the issue board"},
        )
        assert result["tdd_recommended"] is True
        assert "reason" in result

    def test_validator_task(self):
        """Validators have clear inputs/outputs — TDD natural fit."""
        result = classify_tdd_recommendation(
            title="Add email validation to user registration",
            context={"description": "Validate email format and uniqueness before creating user"},
        )
        assert result["tdd_recommended"] is True

    def test_parser_task(self):
        """Parsers transform input → output, perfect for test-first."""
        result = classify_tdd_recommendation(
            title="Parse YAML workflow definitions",
            context={"description": "Parse workflow YAML into WorkflowDefinition objects"},
        )
        assert result["tdd_recommended"] is True

    def test_resolver_task(self):
        """Dependency resolvers have well-defined contracts."""
        result = classify_tdd_recommendation(
            title="Implement dependency resolver for task graph",
            context={"description": "Resolve title-based dependencies to task IDs"},
        )
        assert result["tdd_recommended"] is True

    def test_state_transition_task(self):
        """State machine transitions have clear before/after states."""
        result = classify_tdd_recommendation(
            title="Add issue → resolved status transition",
            context={"description": "Transition issue tasks to resolved with validation"},
        )
        assert result["tdd_recommended"] is True

    def test_computation_task(self):
        """Pure computation tasks with clear inputs/outputs."""
        result = classify_tdd_recommendation(
            title="Calculate task priority scores",
            context={"description": "Score tasks by priority, dependencies, and age"},
        )
        assert result["tdd_recommended"] is True

    def test_explicit_test_mention(self):
        """Tasks that mention testing in their context."""
        result = classify_tdd_recommendation(
            title="Add exclusion guard for claimed tasks",
            context={"testing": "Unit test each guard condition with fixtures"},
        )
        assert result["tdd_recommended"] is True

    def test_domain_model_task(self):
        """Adding fields/enums to domain models."""
        result = classify_tdd_recommendation(
            title="Add ISSUE and RESOLVED to TaskStatus enum",
            context={"files": ["loom/graph/task.py"], "description": "New enum values for issue lifecycle"},
        )
        assert result["tdd_recommended"] is True


# ---------------------------------------------------------------------------
# Negative signals — TDD not recommended
# ---------------------------------------------------------------------------


class TestTDDNotRecommended:
    """Tasks where TDD would be overhead without signal."""

    def test_ui_template_task(self):
        """UI/template work is hard to test-first meaningfully."""
        result = classify_tdd_recommendation(
            title="Update dashboard HTML template with issue panel",
            context={"files": ["loom/dashboard/templates/index.html"], "description": "Add HTML section for issues"},
        )
        assert result["tdd_recommended"] is False

    def test_config_tweak(self):
        """Trivial config changes don't benefit from TDD."""
        result = classify_tdd_recommendation(
            title="Update default timeout in config.yaml",
            context={"complexity": "XS", "description": "Change timeout from 30 to 60"},
        )
        assert result["tdd_recommended"] is False

    def test_documentation_task(self):
        """Docs are not testable."""
        result = classify_tdd_recommendation(
            title="Write README section for issue board",
            context={"description": "Document the loom_issue and loom_issues MCP tools"},
        )
        assert result["tdd_recommended"] is False

    def test_migration_sql_only(self):
        """SQL migrations have no testable Python code."""
        result = classify_tdd_recommendation(
            title="Add tags column to projects table",
            context={"files": ["loom/db/migrations/007_issue_registry.sql"], "description": "ALTER TABLE for tags"},
        )
        assert result["tdd_recommended"] is False

    def test_mcp_tool_wiring(self):
        """Thin MCP tool wrappers (≤15 lines) are glue code."""
        result = classify_tdd_recommendation(
            title="Add loom_issue MCP tool",
            context={"files": ["loom/mcp/tools.py"], "description": "Thin wrapper calling store.create_issue"},
        )
        assert result["tdd_recommended"] is False

    def test_deployment_task(self):
        """Deployment/infra tasks aren't unit-testable."""
        result = classify_tdd_recommendation(
            title="Configure Docker health checks",
            context={"files": ["docker-compose.yml"], "description": "Add healthcheck to postgres service"},
        )
        assert result["tdd_recommended"] is False

    def test_empty_context(self):
        """No context means we can't classify — default to False."""
        result = classify_tdd_recommendation(
            title="Do something",
            context={},
        )
        assert result["tdd_recommended"] is False


# ---------------------------------------------------------------------------
# Edge cases
# ---------------------------------------------------------------------------


class TestTDDEdgeCases:
    """Edge cases for the heuristic."""

    def test_returns_reason(self):
        """Every result includes a reason string."""
        result = classify_tdd_recommendation(
            title="Add parser for config files",
            context={"description": "Parse TOML config into typed objects"},
        )
        assert isinstance(result["reason"], str)
        assert len(result["reason"]) > 0

    def test_returns_signals(self):
        """Result includes which signals fired."""
        result = classify_tdd_recommendation(
            title="Validate task dependencies",
            context={"description": "Check for cycles in dependency graph"},
        )
        assert "signals" in result
        assert isinstance(result["signals"], list)
        assert len(result["signals"]) > 0

    def test_none_context_treated_as_empty(self):
        """None context doesn't crash."""
        result = classify_tdd_recommendation(
            title="Some task",
            context=None,
        )
        assert result["tdd_recommended"] is False


# ---------------------------------------------------------------------------
# TDD instruction block
# ---------------------------------------------------------------------------


class TestTDDInstructionBlock:
    """Tests for the TDD instruction block constant."""

    def test_block_is_importable(self):
        """The instruction block constant exists and is a non-empty string."""
        from loom.skills.tdd import TDD_INSTRUCTION_BLOCK
        assert isinstance(TDD_INSTRUCTION_BLOCK, str)
        assert len(TDD_INSTRUCTION_BLOCK) > 50

    def test_block_contains_red_green_phases(self):
        """The instruction block mentions RED and GREEN phases."""
        from loom.skills.tdd import TDD_INSTRUCTION_BLOCK
        assert "FAIL" in TDD_INSTRUCTION_BLOCK or "RED" in TDD_INSTRUCTION_BLOCK
        assert "pass" in TDD_INSTRUCTION_BLOCK.lower() or "GREEN" in TDD_INSTRUCTION_BLOCK

    def test_block_warns_against_early_implementation(self):
        """Agents are told not to write code before tests."""
        from loom.skills.tdd import TDD_INSTRUCTION_BLOCK
        assert "NOT" in TDD_INSTRUCTION_BLOCK or "before" in TDD_INSTRUCTION_BLOCK
