"""Tests for filename rule - 文件名规则测试."""

from __future__ import annotations

from pathlib import Path

import pytest

from ...models.fileinfo import FileInfo
from ..filename import FilenameRule


class TestFilenameRule:
    """FilenameRule 测试类."""

    @pytest.fixture
    def basic_rules_config(self) -> dict:
        """基础规则配置."""
        return {
            "filename_rules": [
                {
                    "name": "Test Rule",
                    "description": "Test description",
                    "patterns": ["test"],
                    "level": 1,
                    "regex": False,
                    "case_sensitive": False,
                },
            ],
        }

    @pytest.fixture
    def multi_level_rules_config(self) -> dict:
        """多等级规则配置."""
        return {
            "filename_rules": [
                {
                    "name": "Public Rule",
                    "description": "Public level",
                    "patterns": [r"PUB", r"NORMAL"],
                    "level": 1,
                    "regex": True,
                    "case_sensitive": False,
                },
                {
                    "name": "INT Rule",
                    "description": "Internal level",
                    "patterns": [r"INT"],
                    "level": 2,
                    "regex": True,
                    "case_sensitive": False,
                },
                {
                    "name": "Conf Rule",
                    "description": "Confidential level",
                    "patterns": [r"CONF"],
                    "level": 3,
                    "regex": True,
                    "case_sensitive": False,
                },
            ],
        }

    @pytest.fixture
    def sample_fileinfo(self, tmp_path) -> FileInfo:
        """创建样本文件信息."""
        test_file = tmp_path / "test_file.txt"
        test_file.write_text("test content")
        return FileInfo(file_path=str(test_file), root_path=str(tmp_path), file_type=".txt", file_size=12)

    def test_init_with_valid_config(self, basic_rules_config: dict) -> None:
        """测试使用有效配置初始化."""
        rule = FilenameRule(basic_rules_config)
        assert len(rule.rule_configs) == 1
        assert rule.rule_configs[0].name == "Test Rule"

    def test_init_with_empty_config(self) -> None:
        """测试使用空配置初始化."""
        rule = FilenameRule({})
        assert len(rule.rule_configs) == 0

    def test_match_basic_text_match(self, basic_rules_config, tmp_path) -> None:
        """测试基础文本匹配."""
        rule = FilenameRule(basic_rules_config)
        test_file = tmp_path / "my_test_file.txt"
        test_file.write_text("content")
        fileinfo = FileInfo(file_path=str(test_file), root_path=str(tmp_path))

        result = rule.match(fileinfo)
        assert result is not None
        assert result.rule_name == "Test Rule"
        assert result.match_text == "test"
        assert result.analysis_type == "filename"

    def test_match_no_match(self, basic_rules_config, tmp_path) -> None:
        """测试不匹配的情况."""
        rule = FilenameRule(basic_rules_config)
        test_file = tmp_path / "unrelated.txt"
        test_file.write_text("content")
        fileinfo = FileInfo(file_path=str(test_file), root_path=str(tmp_path))

        result = rule.match(fileinfo)
        assert result is None

    def test_match_case_insensitive(self, basic_rules_config, tmp_path) -> None:
        """测试不区分大小写的匹配."""
        rule = FilenameRule(basic_rules_config)
        test_file = tmp_path / "MY_TEST_FILE.txt"
        test_file.write_text("content")
        fileinfo = FileInfo(file_path=str(test_file), root_path=str(tmp_path))

        result = rule.match(fileinfo)
        assert result is not None
        assert result.match_text == "test"

    def test_match_case_sensitive(self, tmp_path: Path) -> None:
        """测试区分大小写的匹配."""
        config = {
            "filename_rules": [
                {
                    "name": "Case Sensitive Rule",
                    "description": "Case sensitive",
                    "patterns": ["TEST"],
                    "level": 1,
                    "regex": False,
                    "case_sensitive": True,
                },
            ],
        }
        rule = FilenameRule(config)

        # 应该匹配
        test_file = tmp_path / "MY_TEST_FILE.txt"
        test_file.write_text("content")
        fileinfo = FileInfo(file_path=str(test_file), root_path=str(tmp_path))
        result = rule.match(fileinfo)
        assert result is not None

        # 不应该匹配
        test_file2 = tmp_path / "my_test_file.txt"
        test_file2.write_text("content")
        fileinfo2 = FileInfo(file_path=str(test_file2), root_path=str(tmp_path))
        result2 = rule.match(fileinfo2)
        assert result2 is None

    def test_match_regex_pattern(self, tmp_path: Path) -> None:
        """测试正则表达式匹配."""
        config = {
            "filename_rules": [
                {
                    "name": "Regex Rule",
                    "description": "Regex pattern",
                    "patterns": [r"\d{3}"],  # 匹配 3 个数字
                    "level": 1,
                    "regex": True,
                    "case_sensitive": False,
                },
            ],
        }
        rule = FilenameRule(config)

        # 应该匹配
        test_file = tmp_path / "file_123.txt"
        test_file.write_text("content")
        fileinfo = FileInfo(file_path=str(test_file), root_path=str(tmp_path))
        result = rule.match(fileinfo)
        assert result is not None
        assert result.match_text == r"\d{3}"
        assert result.match_type == "regex"

        # 不应该匹配
        test_file2 = tmp_path / "file_ab.txt"
        test_file2.write_text("content")
        fileinfo2 = FileInfo(file_path=str(test_file2), root_path=str(tmp_path))
        result2 = rule.match(fileinfo2)
        assert result2 is None

    def test_match_multi_level_detection(self, multi_level_rules_config, tmp_path) -> None:
        """测试多等级检测."""
        rule = FilenameRule(multi_level_rules_config)

        # 文件名包含多个规则模式（PUB 和 INT），应该触发 multi_level
        test_file = tmp_path / "PUB_INT_report.txt"
        test_file.write_text("content")
        fileinfo = FileInfo(file_path=str(test_file), root_path=str(tmp_path))

        result = rule.match(fileinfo)
        assert result is not None

        # 检查 metadata 中是否设置了 filename_multi_level
        import json

        metadata = json.loads(result.metadata)
        assert metadata["filename_multi_level"] == 1

        # 应该返回最高等级的匹配（INT Rule, level 2）
        assert result.rule_name == "INT Rule"

    def test_match_single_level(self, multi_level_rules_config, tmp_path) -> None:
        """测试单等级情况."""
        rule = FilenameRule(multi_level_rules_config)

        # 文件名只匹配一个规则
        test_file = tmp_path / "PUB_report.txt"
        test_file.write_text("content")
        fileinfo = FileInfo(file_path=str(test_file), root_path=str(tmp_path))

        result = rule.match(fileinfo)
        assert result is not None

        import json

        metadata = json.loads(result.metadata)
        assert metadata["filename_multi_level"] == 0
        assert result.rule_name == "Public Rule"

    def test_match_returns_highest_level(self, multi_level_rules_config, tmp_path) -> None:
        """测试返回最高等级的匹配."""
        rule = FilenameRule(multi_level_rules_config)

        # 文件名匹配多个规则，应该返回等级最高的
        test_file = tmp_path / "PUB_INT_CONF_data.xlsx"
        test_file.write_text("content")
        fileinfo = FileInfo(file_path=str(test_file), root_path=str(tmp_path))

        result = rule.match(fileinfo)
        assert result is not None

        # 应该返回 Conf Rule (level 3)
        assert result.rule_name == "Conf Rule"
        assert result.rule_description == "Confidential level"

    def test_match_empty_filename(self, basic_rules_config: dict, tmp_path: Path) -> None:
        """测试空文件名的情况."""
        rule = FilenameRule(basic_rules_config)
        fileinfo = FileInfo(file_path="", root_path=str(tmp_path))

        result = rule.match(fileinfo)
        assert result is None

    def test_match_empty_patterns(self, tmp_path: Path) -> None:
        """测试空模式列表的情况."""
        config = {
            "filename_rules": [
                {
                    "name": "Empty Pattern Rule",
                    "description": "Empty patterns",
                    "patterns": [],
                    "level": 1,
                    "regex": False,
                    "case_sensitive": False,
                },
            ],
        }
        rule = FilenameRule(config)
        test_file = tmp_path / "test.txt"
        test_file.write_text("content")
        fileinfo = FileInfo(file_path=str(test_file), root_path=str(tmp_path))

        result = rule.match(fileinfo)
        assert result is None

    def test_match_multiple_patterns_same_rule(self, tmp_path: Path) -> None:
        """测试同一规则的多个模式匹配."""
        config = {
            "filename_rules": [
                {
                    "name": "Multi-Pattern Rule",
                    "description": "Multiple patterns",
                    "patterns": ["abc", "xyz", "123"],
                    "level": 2,
                    "regex": False,
                    "case_sensitive": False,
                },
            ],
        }
        rule = FilenameRule(config)

        # 匹配第一个模式
        test_file = tmp_path / "file_abc.txt"
        test_file.write_text("content")
        fileinfo = FileInfo(file_path=str(test_file), root_path=str(tmp_path))
        result = rule.match(fileinfo)
        assert result is not None
        assert result.match_text == "abc"

        # 匹配第二个模式
        test_file2 = tmp_path / "file_xyz.txt"
        test_file2.write_text("content")
        fileinfo2 = FileInfo(file_path=str(test_file2), root_path=str(tmp_path))
        result2 = rule.match(fileinfo2)
        assert result2 is not None
        assert result2.match_text == "xyz"

    def test_match_info_structure(self, basic_rules_config, tmp_path) -> None:
        """测试 MatchInfo 对象的结构."""
        rule = FilenameRule(basic_rules_config)
        test_file = tmp_path / "test_document.pdf"
        test_file.write_text("content")
        fileinfo = FileInfo(id=123, file_path=str(test_file), root_path=str(tmp_path), file_type=".pdf")

        result = rule.match(fileinfo)
        assert result is not None
        assert result.file_id == 123
        assert result.rule_name == "Test Rule"
        assert result.rule_description == "Test description"
        assert result.match_type == "text"
        assert result.analysis_type == "filename"
        assert result.line_number == 0
        assert result.match_text == "test"
        assert "test_document.pdf" in result.context_lines[0]
        assert result.is_skipped == 0
        assert result.skip_reason == ""
