"""Tests for deprecation tracking module — Task 51."""

from __future__ import annotations

from services.intelligence_pipeline_v3.deprecation.tracker import (
    DEFAULT_DEPRECATIONS,
    DeprecationEntry,
    DeprecationStatus,
    DeprecationTracker,
    MigrationReport,
)


class TestDeprecationEntry:
    """Task 51: Deprecation lifecycle."""

    def test_create_entry(self):
        entry = DeprecationEntry.create(
            component_name="VLLMClient",
            component_path="services/extractor/vllm_client.py",
            reason="Replaced by OpenAICompatibleClient",
            known_consumers=["worker.py", "thesis_llm.py"],
            replacement="services/shared/inference/clients/openai_compatible.py",
        )
        assert entry.status == DeprecationStatus.DEPRECATED
        assert entry.migration_progress == 0.0
        assert not entry.all_consumers_migrated

    def test_mark_consumer_migrated(self):
        entry = DeprecationEntry.create(
            component_name="VLLMClient",
            component_path="services/extractor/vllm_client.py",
            reason="Replaced",
            known_consumers=["worker.py", "thesis_llm.py"],
        )
        entry.mark_consumer_migrated("worker.py")
        assert entry.migration_progress == 0.5
        entry.mark_consumer_migrated("thesis_llm.py")
        assert entry.migration_progress == 1.0
        assert entry.all_consumers_migrated
        assert entry.status == DeprecationStatus.MIGRATION_COMPLETE

    def test_approve_removal_requires_all_migrated(self):
        entry = DeprecationEntry.create(
            component_name="v2_prompt",
            component_path="services/extractor/prompts.py",
            reason="Replaced by staged extraction",
            known_consumers=["worker.py"],
        )
        # Cannot approve before migration
        assert not entry.approve_removal("admin")
        # After migration
        entry.mark_consumer_migrated("worker.py")
        assert entry.approve_removal("admin")
        assert entry.removal_approved

    def test_mark_removed(self):
        entry = DeprecationEntry.create(
            component_name="truncation",
            component_path="services/extractor/prompts.py",
            reason="Replaced by segmenter",
            known_consumers=["prompts.py"],
        )
        entry.mark_consumer_migrated("prompts.py")
        entry.approve_removal("admin")
        entry.mark_removed()
        assert entry.status == DeprecationStatus.REMOVED
        assert entry.removed_at is not None

    def test_no_known_consumers_means_ready(self):
        entry = DeprecationEntry.create(
            component_name="old_defaults",
            component_path="services/shared/config.py",
            reason="Conflicting defaults removed",
            known_consumers=[],
        )
        assert entry.all_consumers_migrated
        assert entry.migration_progress == 1.0


class TestDeprecationTracker:
    """Task 51: Full deprecation tracking workflow."""

    def test_add_and_get(self):
        tracker = DeprecationTracker()
        entry = DeprecationEntry.create(
            component_name="VLLMClient",
            component_path="vllm_client.py",
            reason="replaced",
        )
        tracker.add(entry)
        assert tracker.get("VLLMClient") is entry

    def test_mark_migrated(self):
        tracker = DeprecationTracker()
        entry = DeprecationEntry.create(
            component_name="VLLMClient",
            component_path="vllm_client.py",
            reason="replaced",
            known_consumers=["worker.py"],
        )
        tracker.add(entry)
        assert tracker.mark_migrated("VLLMClient", "worker.py")
        assert tracker.get("VLLMClient").all_consumers_migrated

    def test_can_remove(self):
        tracker = DeprecationTracker()
        entry = DeprecationEntry.create(
            component_name="VLLMClient",
            component_path="vllm_client.py",
            reason="replaced",
            known_consumers=["worker.py"],
        )
        tracker.add(entry)
        assert not tracker.can_remove("VLLMClient")
        tracker.mark_migrated("VLLMClient", "worker.py")
        assert not tracker.can_remove("VLLMClient")  # Not approved yet
        tracker.approve_removal("VLLMClient", "admin")
        assert tracker.can_remove("VLLMClient")

    def test_pending_removals(self):
        tracker = DeprecationTracker()
        e1 = DeprecationEntry.create(
            "comp1", "path1", "reason", known_consumers=["c1"]
        )
        e2 = DeprecationEntry.create(
            "comp2", "path2", "reason", known_consumers=["c2"]
        )
        tracker.add(e1)
        tracker.add(e2)
        tracker.mark_migrated("comp1", "c1")
        tracker.approve_removal("comp1", "admin")
        assert len(tracker.pending_removals) == 1
        assert tracker.pending_removals[0].component_name == "comp1"

    def test_generate_report(self):
        tracker = DeprecationTracker()
        e1 = DeprecationEntry.create(
            "VLLMClient", "path1", "replaced", known_consumers=["w1", "w2"]
        )
        e2 = DeprecationEntry.create(
            "v2_prompt", "path2", "replaced", known_consumers=["w1"]
        )
        tracker.add(e1)
        tracker.add(e2)
        tracker.mark_migrated("VLLMClient", "w1")
        tracker.mark_migrated("v2_prompt", "w1")
        report = tracker.generate_report()
        assert report.total_components == 2
        assert report.deprecated == 1  # VLLMClient still has w2
        assert report.migration_complete == 1  # v2_prompt is done
        assert len(report.blocked_removals) == 1


class TestDefaultDeprecations:
    """Task 51: Default deprecation entries cover required components."""

    def test_default_entries_defined(self):
        assert len(DEFAULT_DEPRECATIONS) >= 5

    def test_vllm_client_in_defaults(self):
        names = [d["component_name"] for d in DEFAULT_DEPRECATIONS]
        assert "VLLMClient" in names

    def test_v2_prompt_in_defaults(self):
        names = [d["component_name"] for d in DEFAULT_DEPRECATIONS]
        assert "v2_extraction_prompt" in names

    def test_provider_branching_in_defaults(self):
        names = [d["component_name"] for d in DEFAULT_DEPRECATIONS]
        assert "provider_branching" in names

    def test_truncation_in_defaults(self):
        names = [d["component_name"] for d in DEFAULT_DEPRECATIONS]
        assert "8000_char_truncation" in names

    def test_compatibility_adapter_in_defaults(self):
        names = [d["component_name"] for d in DEFAULT_DEPRECATIONS]
        assert "compatibility_adapter" in names


class TestMigrationReport:
    """Task 51.5: Archive final migration reports."""

    def test_report_to_dict(self):
        entries = [
            DeprecationEntry.create("c1", "p1", "r", known_consumers=["x"]),
        ]
        report = MigrationReport.generate(entries)
        d = report.to_dict()
        assert "total_components" in d
        assert "blocked_removals" in d
