"""context_writer.py — CLAUDE.md 标签隔离读写测试"""

from __future__ import annotations

from pathlib import Path

import pytest

from index1.cognitive.context_writer import read_tagged_content, write_tagged_content


class TestWriteTaggedContent:
    """write_tagged_content 单元测试"""

    def test_create_new_file(self, tmp_path: Path):
        """文件不存在时创建并写入标签"""
        target = tmp_path / "CLAUDE.md"
        ok = write_tagged_content(target, "index1-context", "hello world")
        assert ok
        assert target.exists()
        text = target.read_text()
        assert "<index1-context>" in text
        assert "hello world" in text
        assert "</index1-context>" in text

    def test_replace_existing_tag(self, tmp_path: Path):
        """已有标签时替换内容"""
        target = tmp_path / "CLAUDE.md"
        target.write_text(
            "# Project\n\n<index1-context>\nold content\n</index1-context>\n\n# Footer\n"
        )
        ok = write_tagged_content(target, "index1-context", "new content")
        assert ok
        text = target.read_text()
        assert "new content" in text
        assert "old content" not in text
        # 标签外内容不受影响
        assert "# Project" in text
        assert "# Footer" in text

    def test_append_to_existing_file(self, tmp_path: Path):
        """文件中无标签时追加到末尾"""
        target = tmp_path / "CLAUDE.md"
        target.write_text("# My Project\n\nSome content.\n")
        ok = write_tagged_content(target, "index1-context", "appended")
        assert ok
        text = target.read_text()
        assert "# My Project" in text
        assert "Some content." in text
        assert "<index1-context>\nappended\n</index1-context>" in text

    def test_coexist_with_claude_mem_tags(self, tmp_path: Path):
        """与 claude-mem 标签互不干扰"""
        target = tmp_path / "CLAUDE.md"
        target.write_text(
            "<claude-mem-context>\nmem stuff\n</claude-mem-context>\n\n# Project\n"
        )
        ok = write_tagged_content(target, "index1-context", "index1 stuff")
        assert ok
        text = target.read_text()
        # claude-mem 标签完整保留
        assert "<claude-mem-context>" in text
        assert "mem stuff" in text
        assert "</claude-mem-context>" in text
        # index1 标签已添加
        assert "<index1-context>" in text
        assert "index1 stuff" in text

    def test_truncate_oversized_content(self, tmp_path: Path):
        """超过 10KB 的内容被截断"""
        target = tmp_path / "CLAUDE.md"
        big_content = "x" * 20000
        ok = write_tagged_content(target, "index1-context", big_content)
        assert ok
        text = target.read_text()
        # 标签内容被截断至 10240
        content = read_tagged_content(target, "index1-context")
        assert content is not None
        assert len(content) <= 10240

    def test_invalid_tag_name(self, tmp_path: Path):
        """非法标签名被拒绝"""
        target = tmp_path / "CLAUDE.md"
        assert not write_tagged_content(target, "bad tag!", "content")
        assert not write_tagged_content(target, "", "content")

    def test_non_string_content(self, tmp_path: Path):
        """非字符串内容被拒绝"""
        target = tmp_path / "CLAUDE.md"
        assert not write_tagged_content(target, "test", 123)  # type: ignore[arg-type]

    def test_atomic_write(self, tmp_path: Path):
        """写入失败时不损坏原文件"""
        target = tmp_path / "CLAUDE.md"
        target.write_text("original content")
        # 模拟不可写目录不好测试，但至少确认 tmp 文件被清理
        ok = write_tagged_content(target, "test-tag", "new content")
        assert ok
        # 无残留 tmp 文件
        assert not (tmp_path / "CLAUDE.md.index1.tmp").exists()

    def test_idempotent_write(self, tmp_path: Path):
        """连续写入幂等"""
        target = tmp_path / "CLAUDE.md"
        write_tagged_content(target, "index1-context", "v1")
        write_tagged_content(target, "index1-context", "v2")
        write_tagged_content(target, "index1-context", "v3")
        text = target.read_text()
        # 只有一个标签对
        assert text.count("<index1-context>") == 1
        assert text.count("</index1-context>") == 1
        assert "v3" in text
        assert "v1" not in text


class TestReadTaggedContent:
    """read_tagged_content 单元测试"""

    def test_read_existing_tag(self, tmp_path: Path):
        """读取已有标签内容"""
        target = tmp_path / "CLAUDE.md"
        target.write_text(
            "# Header\n<index1-context>\nmy content\n</index1-context>\n# Footer\n"
        )
        content = read_tagged_content(target, "index1-context")
        assert content == "my content"

    def test_read_nonexistent_tag(self, tmp_path: Path):
        """标签不存在时返回 None"""
        target = tmp_path / "CLAUDE.md"
        target.write_text("# Header\nno tags here\n")
        assert read_tagged_content(target, "index1-context") is None

    def test_read_nonexistent_file(self, tmp_path: Path):
        """文件不存在时返回 None"""
        assert read_tagged_content(tmp_path / "nope.md", "index1-context") is None

    def test_read_empty_tag(self, tmp_path: Path):
        """空标签返回 None"""
        target = tmp_path / "CLAUDE.md"
        target.write_text("<index1-context>\n</index1-context>\n")
        assert read_tagged_content(target, "index1-context") is None

    def test_read_invalid_tag_name(self, tmp_path: Path):
        """非法标签名返回 None"""
        target = tmp_path / "CLAUDE.md"
        target.write_text("<bad>content</bad>")
        assert read_tagged_content(target, "bad tag!") is None

    def test_read_multiline_content(self, tmp_path: Path):
        """多行内容正确读取"""
        target = tmp_path / "CLAUDE.md"
        target.write_text(
            "<index1-context>\nline1\nline2\nline3\n</index1-context>\n"
        )
        content = read_tagged_content(target, "index1-context")
        assert content == "line1\nline2\nline3"

    def test_roundtrip(self, tmp_path: Path):
        """写入后读取一致"""
        target = tmp_path / "CLAUDE.md"
        original = "files: hooks.py, cli.py\ncategories: bugfix:2 feature:1"
        write_tagged_content(target, "index1-context", original)
        result = read_tagged_content(target, "index1-context")
        assert result == original
