"""规则 YAML 校验器。"""

from __future__ import annotations

import importlib
import sys
from dataclasses import dataclass

import yaml
from pydantic import ValidationError

from leaudit.dsl.loader import parse_rules_yaml_text
from leaudit.dsl.validator import DSLValidationError, validate as validate_rules


@dataclass(frozen=True)
class RuleValidationPayload:
    """规则校验结果。"""

    valid: bool
    ruleType: str | None = None
    ruleName: str | None = None
    versionNo: str | None = None
    ruleCount: int = 0
    extractCount: int = 0
    errors: list[str] | None = None


class RuleValidator:
    """负责规则 YAML 的语法与 DSL 语义校验。"""

    _CHECK_MODULES = (
        "leaudit.engine.checks.required",
        "leaudit.engine.checks.compare",
        "leaudit.engine.checks.format_check",
        "leaudit.engine.checks.text",
        "leaudit.engine.checks.multi_entity",
        "leaudit.engine.checks.visual",
        "leaudit.engine.checks.external",
        "leaudit.engine.checks.assert_check",
        "leaudit.engine.checks.code_check",
        "leaudit.engine.checks.ai_check",
    )

    def ValidateYaml(self, YamlText: str) -> RuleValidationPayload:
        """校验 YAML 并返回摘要结果。"""
        try:
            RulesFile = parse_rules_yaml_text(YamlText)
            self._EnsureChecksImported()
            validate_rules(RulesFile, registered_primitives=None)
        except yaml.YAMLError as Error:
            return RuleValidationPayload(valid=False, errors=[f"YAML 语法错误: {Error}"])
        except ValidationError as Error:
            return RuleValidationPayload(valid=False, errors=[f"Schema 校验失败: {Error}"])
        except DSLValidationError as Error:
            return RuleValidationPayload(valid=False, errors=[f"DSL 校验失败: {Error}"])
        except Exception as Error:
            return RuleValidationPayload(valid=False, errors=[f"规则校验失败: {Error}"])

        return RuleValidationPayload(
            valid=True,
            ruleType=RulesFile.metadata.type_id,
            ruleName=RulesFile.metadata.name,
            versionNo=RulesFile.metadata.version,
            ruleCount=len(RulesFile.flat_rules),
            extractCount=len(RulesFile.flat_extract),
            errors=[],
        )

    def ParseValidated(self, YamlText: str):
        """解析并返回已通过完整校验的 RulesFile。"""
        Validation = self.ValidateYaml(YamlText)
        if not Validation.valid:
            raise ValueError("; ".join(Validation.errors or ["规则校验失败"]))
        return parse_rules_yaml_text(YamlText)

    def _EnsureChecksImported(self) -> None:
        """确保所有检查器模块已注册。"""
        for ModuleName in self._CHECK_MODULES:
            try:
                if ModuleName in sys.modules:
                    importlib.reload(sys.modules[ModuleName])
                else:
                    importlib.import_module(ModuleName)
            except Exception:
                continue
