"""Tests for cortex.core.task_mode — Task-Mode Classification (#362)."""

from __future__ import annotations

import pytest

from cortex.core.task_mode import TaskMode, TaskModeClassifier, TaskModeResult


class TestTaskModeEnum:
    """TaskMode enum covers all 8 modes."""

    def test_all_modes_present(self):
        expected = {
            "continue_project", "design", "write", "plan",
            "decide", "debug", "recall_history", "future_commitment",
        }
        actual = {m.value for m in TaskMode}
        assert actual == expected

    def test_string_enum(self):
        assert TaskMode.DEBUG == "debug"
        assert TaskMode("design") == TaskMode.DESIGN


class TestTaskModeResult:
    """TaskModeResult dataclass."""

    def test_basic(self):
        r = TaskModeResult(mode=TaskMode.DEBUG, confidence=0.8, signals=["kw:error"])
        assert r.mode == TaskMode.DEBUG
        assert r.confidence == 0.8
        assert r.signals == ["kw:error"]

    def test_defaults(self):
        r = TaskModeResult(mode=TaskMode.PLAN, confidence=0.5)
        assert r.signals == []


class TestTaskModeClassifier:
    """TaskModeClassifier deterministic classification tests."""

    @pytest.fixture
    def classifier(self):
        return TaskModeClassifier()

    # ---------------------------------------------------------------
    # Mode detection for each of 8 modes
    # ---------------------------------------------------------------

    def test_debug_keywords(self, classifier):
        result = classifier.classify("There's a bug in the login flow, it crashes on submit")
        assert result.mode == TaskMode.DEBUG
        assert result.confidence > 0.3

    def test_debug_pattern(self, classifier):
        result = classifier.classify("Why does the server crash when I send a POST?")
        assert result.mode == TaskMode.DEBUG

    def test_design_keywords(self, classifier):
        result = classifier.classify("What architecture pattern should we use for the API schema?")
        assert result.mode == TaskMode.DESIGN
        assert result.confidence > 0.3

    def test_design_pattern(self, classifier):
        result = classifier.classify("How should we design the database layer?")
        assert result.mode == TaskMode.DESIGN

    def test_plan_keywords(self, classifier):
        result = classifier.classify("What's our roadmap for the sprint planning milestone?")
        assert result.mode == TaskMode.PLAN
        assert result.confidence > 0.3

    def test_plan_pattern(self, classifier):
        result = classifier.classify("What should we work on next for the backlog?")
        assert result.mode == TaskMode.PLAN

    def test_decide_keywords(self, classifier):
        result = classifier.classify("Should we choose React or Vue? Compare the pros and cons")
        assert result.mode == TaskMode.DECIDE
        assert result.confidence > 0.3

    def test_decide_pattern(self, classifier):
        result = classifier.classify("Which would be better for our use case?")
        assert result.mode == TaskMode.DECIDE

    def test_continue_project_keywords(self, classifier):
        result = classifier.classify("Let's continue where we left off on the pending work")
        assert result.mode == TaskMode.CONTINUE_PROJECT
        assert result.confidence > 0.3

    def test_continue_project_pattern(self, classifier):
        result = classifier.classify("Where did we leave off last time?")
        assert result.mode == TaskMode.CONTINUE_PROJECT

    def test_write_keywords(self, classifier):
        result = classifier.classify("Help me draft a blog post about the new documentation")
        assert result.mode == TaskMode.WRITE
        assert result.confidence > 0.3

    def test_write_pattern(self, classifier):
        result = classifier.classify("Write a README for the project")
        assert result.mode == TaskMode.WRITE

    def test_recall_history_keywords(self, classifier):
        result = classifier.classify("Do you remember what we discussed previously about memory?")
        assert result.mode == TaskMode.RECALL_HISTORY
        assert result.confidence > 0.3

    def test_recall_history_pattern(self, classifier):
        result = classifier.classify("What did we decide about the database?")
        assert result.mode == TaskMode.RECALL_HISTORY

    def test_future_commitment_keywords(self, classifier):
        result = classifier.classify("When is the deadline for the deliverable? Check the schedule")
        assert result.mode == TaskMode.FUTURE_COMMITMENT
        assert result.confidence > 0.3

    def test_future_commitment_pattern(self, classifier):
        result = classifier.classify("Remind me to submit the report by Friday")
        assert result.mode == TaskMode.FUTURE_COMMITMENT

    # ---------------------------------------------------------------
    # Confidence scoring
    # ---------------------------------------------------------------

    def test_strong_signals_high_confidence(self, classifier):
        # Multiple debug keywords + pattern → high confidence
        result = classifier.classify(
            "There's a bug causing an error and the traceback shows a crash in the exception handler"
        )
        assert result.mode == TaskMode.DEBUG
        assert result.confidence >= 0.6

    def test_weak_signal_low_confidence(self, classifier):
        # Single keyword, could be ambiguous
        result = classifier.classify("Check the logs")
        assert result.confidence < 0.6

    def test_multiple_keywords_boost_confidence(self, classifier):
        single = classifier.classify("Fix the bug")
        multiple = classifier.classify("Fix the bug, there's an error in the crash logs with an exception")
        assert multiple.confidence > single.confidence

    # ---------------------------------------------------------------
    # Unknown / ambiguous / empty queries
    # ---------------------------------------------------------------

    def test_empty_query(self, classifier):
        result = classifier.classify("")
        assert result.mode == TaskMode.RECALL_HISTORY  # default
        assert result.confidence == 0.0
        assert "empty_query" in result.signals

    def test_whitespace_query(self, classifier):
        result = classifier.classify("   ")
        assert result.confidence == 0.0

    def test_no_signals(self, classifier):
        result = classifier.classify("Hello there, how are you today?")
        assert result.mode == TaskMode.RECALL_HISTORY  # default
        assert result.confidence <= 0.15

    def test_custom_default_mode(self):
        classifier = TaskModeClassifier(default_mode=TaskMode.PLAN)
        result = classifier.classify("")
        assert result.mode == TaskMode.PLAN

    # ---------------------------------------------------------------
    # Context hints
    # ---------------------------------------------------------------

    def test_context_task_hint(self, classifier):
        result = classifier.classify(
            "What's happening with the project?",
            context={"task_hint": "debug"},
        )
        assert result.mode == TaskMode.DEBUG

    def test_context_session_type_coding(self, classifier):
        # "coding" session type boosts debug/design/continue_project
        result_without = classifier.classify("Show me the logs")
        result_with = classifier.classify(
            "Show me the logs",
            context={"session_type": "coding"},
        )
        # Both should detect debug (logs keyword), but context should boost confidence
        assert result_with.mode == TaskMode.DEBUG

    # ---------------------------------------------------------------
    # Signals list populated
    # ---------------------------------------------------------------

    def test_signals_include_keywords(self, classifier):
        result = classifier.classify("Fix the error and debug the crash")
        assert any(s.startswith("kw:") for s in result.signals)

    def test_signals_include_patterns(self, classifier):
        result = classifier.classify("Why does the server fail on POST?")
        assert any(s.startswith("pat:") for s in result.signals)

    def test_context_signals_included(self, classifier):
        result = classifier.classify(
            "Something about the project",
            context={"task_hint": "debug"},
        )
        assert "ctx:task_hint" in result.signals
