from sqlalchemy import create_engine
from sqlalchemy.orm import Session
from sqlalchemy.pool import StaticPool

from app.models import Base
from app.models.logs import OperationLog
from app.models.knowledge import Knowledge, KnowledgeManifest, KnowledgeSourceSnapshot, KnowledgeVersion
from app.services.knowledge_catalog_cache_service import KnowledgeCatalogCacheService


class _RedisRecorder:
    def __init__(self) -> None:
        self.increments: list[str] = []

    def incr(self, key: str) -> None:
        self.increments.append(key)


def _database() -> Session:
    engine = create_engine("sqlite:///:memory:", connect_args={"check_same_thread": False}, poolclass=StaticPool)
    Base.metadata.create_all(engine)
    return Session(engine)


def _knowledge() -> Knowledge:
    return Knowledge(
        id=1,
        name="测试知识库",
        feishu_space_id="space-1",
        feishu_node_id="node-1",
        status=0,
        knowledge_type="general",
        review_mode="manual",
    )


def test_all_agent_knowledge_cache_is_invalidated_after_each_committed_change(monkeypatch):
    redis = _RedisRecorder()
    monkeypatch.setattr(
        "app.services.knowledge_catalog_cache_service.get_sync_redis_client", lambda: redis
    )
    with _database() as db:
        knowledge = _knowledge()
        db.add(knowledge)
        db.commit()

        knowledge.status = 1
        db.commit()

        snapshot = KnowledgeSourceSnapshot(
            id=1,
            knowledge_id=knowledge.id,
            source_title="标题",
            source_content="内容",
            content_hash="snapshot-hash",
            source_identifier="space-1/node-1",
        )
        db.add(snapshot)
        db.flush()
        version = KnowledgeVersion(
            id=1,
            knowledge_id=knowledge.id,
            snapshot_id=snapshot.id,
            version_no=1,
            status="published",
            quality_status="passed",
            processing_rule_version="test-v1",
        )
        db.add(version)
        db.flush()
        db.add(
            KnowledgeManifest(
                id=1,
                knowledge_id=knowledge.id,
                version_id=version.id,
                purpose="用途",
                applicable_questions="适用",
                inapplicable_questions="不适用",
                core_topics="主题",
                content_hash="manifest-hash",
            )
        )
        db.commit()

    assert redis.increments == [KnowledgeCatalogCacheService.VERSION_KEY] * 3


def test_unrelated_log_changes_do_not_invalidate_agent_knowledge_cache(monkeypatch):
    redis = _RedisRecorder()
    monkeypatch.setattr(
        "app.services.knowledge_catalog_cache_service.get_sync_redis_client", lambda: redis
    )
    with _database() as db:
        db.add(OperationLog(module="auth", action="login", result="success"))
        db.commit()

    assert redis.increments == []


def test_rolled_back_knowledge_change_does_not_invalidate_cache(monkeypatch):
    redis = _RedisRecorder()
    monkeypatch.setattr(
        "app.services.knowledge_catalog_cache_service.get_sync_redis_client", lambda: redis
    )
    with _database() as db:
        db.add(_knowledge())
        db.flush()
        db.rollback()

    assert redis.increments == []
