"""Tests for network source, deduplication, and navigation modules."""

from __future__ import annotations

import hashlib

import pytest

from cyberbrain26.knowledge_plane import (
    DeduplicationEngine,
    DocumentTrust,
    KnowledgeDocument,
    KnowledgeNavigator,
    KnowledgeSource,
    NetworkSourceConfig,
    Sensitivity,
)


def approved_source() -> KnowledgeSource:
    return KnowledgeSource(
        source_id="local-notes",
        source_uri="file:///knowledge/notes",
        trust=DocumentTrust.REVIEWED,
        sensitivity=Sensitivity.PERSONAL,
        approved=True,
    )


def test_deduplication_exact_hash() -> None:
    engine = DeduplicationEngine()
    content = b"hello world"
    doc = KnowledgeDocument(
        document_id="doc1",
        source_id="src1",
        source_uri="file:///test.txt",
        content_sha256=hashlib.sha256(content).hexdigest(),
        media_type="text/plain",
        trust=DocumentTrust.EXTERNAL,
        sensitivity=Sensitivity.PERSONAL,
        status=__import__("cyberbrain26.knowledge_plane.contracts", fromlist=["DocumentStatus"]).DocumentStatus.REGISTERED,
        metadata={},
        created_at=0.0,
        updated_at=0.0,
    )
    result = engine.check_duplicate(content, "file:///test.txt", [doc])
    assert result.is_duplicate is True
    assert result.recommended_action == "skip"
    assert len(result.candidates) == 1
    assert result.candidates[0].match_type == "exact_hash"


def test_deduplication_no_duplicate() -> None:
    engine = DeduplicationEngine()
    content = b"hello world"
    result = engine.check_duplicate(content, "file:///test.txt", [])
    assert result.is_duplicate is False
    assert result.recommended_action == "register"


def test_deduplication_batch() -> None:
    engine = DeduplicationEngine()
    items = [(b"hello", "url1"), (b"world", "url2"), (b"hello", "url3")]
    results = engine.deduplicate_batch(items, [])
    assert len(results) == 3
    # First and third have same content hash
    assert results[0][1].is_duplicate is False
    assert results[1][1].is_duplicate is False
    assert results[2][1].is_duplicate is True


def test_navigator_topics() -> None:
    nav = KnowledgeNavigator()
    doc = KnowledgeDocument(
        document_id="doc1",
        source_id="src1",
        source_uri="file:///test.txt",
        content_sha256="abc",
        media_type="text/plain",
        trust=DocumentTrust.EXTERNAL,
        sensitivity=Sensitivity.PERSONAL,
        status=__import__("cyberbrain26.knowledge_plane.contracts", fromlist=["DocumentStatus"]).DocumentStatus.REGISTERED,
        metadata={"topic": "research", "tags": "ai,ml"},
        created_at=0.0,
        updated_at=0.0,
    )
    nav.add_document(doc)
    assert "research" in nav.get_topics()
    assert nav.get_documents_by_topic("research") == ["doc1"]
    assert "ai" in nav.get_all_tags()
    assert "ml" in nav.get_all_tags()


def test_navigator_search() -> None:
    nav = KnowledgeNavigator()
    doc = KnowledgeDocument(
        document_id="doc1",
        source_id="src1",
        source_uri="file:///test.txt",
        content_sha256="abc",
        media_type="text/plain",
        trust=DocumentTrust.EXTERNAL,
        sensitivity=Sensitivity.PERSONAL,
        status=__import__("cyberbrain26.knowledge_plane.contracts", fromlist=["DocumentStatus"]).DocumentStatus.REGISTERED,
        metadata={"description": "AI research paper"},
        created_at=0.0,
        updated_at=0.0,
    )
    nav.add_document(doc)
    results = nav.search_by_keyword("ai", [doc])
    assert "doc1" in results


def test_navigator_cluster_by_source() -> None:
    nav = KnowledgeNavigator()
    docs = [
        KnowledgeDocument(
            document_id="doc1",
            source_id="src1",
            source_uri="https://example.com/page1",
            content_sha256="abc",
            media_type="text/plain",
            trust=DocumentTrust.EXTERNAL,
            sensitivity=Sensitivity.PERSONAL,
            status=__import__("cyberbrain26.knowledge_plane.contracts", fromlist=["DocumentStatus"]).DocumentStatus.REGISTERED,
            metadata={},
            created_at=0.0,
            updated_at=0.0,
        ),
        KnowledgeDocument(
            document_id="doc2",
            source_id="src2",
            source_uri="https://other.com/page2",
            content_sha256="def",
            media_type="text/plain",
            trust=DocumentTrust.EXTERNAL,
            sensitivity=Sensitivity.PERSONAL,
            status=__import__("cyberbrain26.knowledge_plane.contracts", fromlist=["DocumentStatus"]).DocumentStatus.REGISTERED,
            metadata={},
            created_at=0.0,
            updated_at=0.0,
        ),
    ]
    clusters = nav.cluster_by_source(docs)
    assert "example.com" in clusters
    assert "other.com" in clusters


def test_network_source_config_defaults() -> None:
    config = NetworkSourceConfig(source_id="test")
    assert config.source_id == "test"
    assert config.timeout == 30.0
    assert config.max_content_bytes == 10_000_000


def test_network_source_validate_url() -> None:
    from cyberbrain26.knowledge_plane.network_source import NetworkSourceAdapter

    with pytest.raises(ValueError, match="unsupported URL scheme"):
        NetworkSourceAdapter._validate_url("ftp://example.com")

    with pytest.raises(ValueError, match="must have a hostname"):
        NetworkSourceAdapter._validate_url("https://")

    # Should not raise
    NetworkSourceAdapter._validate_url("https://example.com/path")


def test_network_source_html_extraction() -> None:
    from cyberbrain26.knowledge_plane.network_source import NetworkSourceAdapter

    html = b"<html><head><style>body{}</style></head><body><script>alert('x')</script><p>Hello World</p></body></html>"
    result = NetworkSourceAdapter._extract_html(html)
    assert "Hello World" in result
    assert "alert" not in result
    assert "body{}" not in result
