"""
tests/test_sentinel_taxonomy.py — Unit tests for sentinel.taxonomy.

Coverage:
  - Category constants (CONTEXT_DEGRADATION, MEMORY_ARCHITECTURE, etc.)
  - ALL_TAXONOMY union
  - PICKER_OPTIONS structure
  - PROACTIVE_SIGNALS + REACTIVE_TRIGGERS
  - HEDGING_PHRASES + SYCOPHANCY_PHRASES
"""

from __future__ import annotations

import unittest

from sentinel.taxonomy import (
    ALL_TAXONOMY,
    CONTEXT_DEGRADATION,
    FAILURE_MODES,
    HEDGING_PHRASES,
    MEMORY_ARCHITECTURE,
    PICKER_OPTIONS,
    PROACTIVE_SIGNALS,
    REACTIVE_TRIGGERS,
    REASONING_GROUNDING,
    SYCOPHANCY_PHRASES,
)


class TestCategories(unittest.TestCase):
    """Taxonomy category dicts."""

    def test_context_degradation_ids(self):
        for key in CONTEXT_DEGRADATION:
            self.assertTrue(key.startswith("CD-"), f"Bad prefix: {key}")

    def test_memory_architecture_ids(self):
        for key in MEMORY_ARCHITECTURE:
            self.assertTrue(key.startswith("MA-"), f"Bad prefix: {key}")

    def test_failure_modes_ids(self):
        for key in FAILURE_MODES:
            self.assertTrue(key.startswith("FM-"), f"Bad prefix: {key}")

    def test_reasoning_grounding_ids(self):
        for key in REASONING_GROUNDING:
            self.assertTrue(key.startswith("RG-"), f"Bad prefix: {key}")

    def test_non_empty_descriptions(self):
        for cat in (CONTEXT_DEGRADATION, MEMORY_ARCHITECTURE,
                    FAILURE_MODES, REASONING_GROUNDING):
            for k, v in cat.items():
                self.assertTrue(len(v) > 0, f"Empty description for {k}")


class TestAllTaxonomy(unittest.TestCase):
    """ALL_TAXONOMY union."""

    def test_is_superset(self):
        for k in CONTEXT_DEGRADATION:
            self.assertIn(k, ALL_TAXONOMY)
        for k in MEMORY_ARCHITECTURE:
            self.assertIn(k, ALL_TAXONOMY)
        for k in FAILURE_MODES:
            self.assertIn(k, ALL_TAXONOMY)
        for k in REASONING_GROUNDING:
            self.assertIn(k, ALL_TAXONOMY)

    def test_no_duplicates(self):
        total = (len(CONTEXT_DEGRADATION) + len(MEMORY_ARCHITECTURE) +
                 len(FAILURE_MODES) + len(REASONING_GROUNDING))
        self.assertEqual(len(ALL_TAXONOMY), total)

    def test_minimum_count(self):
        self.assertGreaterEqual(len(ALL_TAXONOMY), 30)


class TestPickerOptions(unittest.TestCase):
    """PICKER_OPTIONS for Copilot-style picker."""

    def test_is_list_of_tuples(self):
        for item in PICKER_OPTIONS:
            self.assertIsInstance(item, tuple)
            self.assertEqual(len(item), 2)

    def test_ids_in_taxonomy(self):
        for tid, label in PICKER_OPTIONS:
            self.assertIn(tid, ALL_TAXONOMY, f"Picker {tid} not in taxonomy")

    def test_minimum_options(self):
        self.assertGreaterEqual(len(PICKER_OPTIONS), 8)


class TestProactiveSignals(unittest.TestCase):
    """PROACTIVE_SIGNALS dict."""

    def test_keys_are_strings(self):
        for key in PROACTIVE_SIGNALS:
            self.assertIsInstance(key, str)

    def test_values_are_taxonomy_ids(self):
        for key, phrases in PROACTIVE_SIGNALS.items():
            self.assertIn(key, ALL_TAXONOMY,
                          f"Proactive signal key {key} not in taxonomy")
            self.assertIsInstance(phrases, list,
                                 f"Proactive signal {key} should be list")


class TestReactiveTriggers(unittest.TestCase):
    """REACTIVE_TRIGGERS list of (regex, taxonomy_id) tuples."""

    def test_structure(self):
        for item in REACTIVE_TRIGGERS:
            self.assertIsInstance(item, tuple)
            self.assertEqual(len(item), 2)
            pattern, tid = item
            self.assertIsInstance(pattern, str)
            self.assertIn(tid, ALL_TAXONOMY, f"Trigger maps to unknown {tid}")

    def test_minimum_count(self):
        self.assertGreaterEqual(len(REACTIVE_TRIGGERS), 15)


class TestPhrases(unittest.TestCase):
    """HEDGING_PHRASES and SYCOPHANCY_PHRASES."""

    def test_hedging_non_empty(self):
        self.assertGreaterEqual(len(HEDGING_PHRASES), 10)
        for p in HEDGING_PHRASES:
            self.assertIsInstance(p, str)

    def test_sycophancy_non_empty(self):
        self.assertGreaterEqual(len(SYCOPHANCY_PHRASES), 8)
        for p in SYCOPHANCY_PHRASES:
            self.assertIsInstance(p, str)


if __name__ == "__main__":
    unittest.main()
