"""
Intent rule tester for AI Service.
[AC-AISVC-96] Intent rule testing service with conflict detection.
"""

import logging
import re
from dataclasses import dataclass, field
from typing import Any

from app.models.entities import IntentRule
from app.services.intent.router import IntentRouter

logger = logging.getLogger(__name__)


@dataclass
class IntentRuleTestCase:
    """Result of testing a single message against a rule."""

    message: str
    matched: bool
    matched_keywords: list[str] = field(default_factory=list)
    matched_patterns: list[str] = field(default_factory=list)
    match_type: str | None = None
    priority: int = 0
    priority_rank: int = 0
    conflict_rules: list[dict[str, Any]] = field(default_factory=list)
    reason: str | None = None

    def to_dict(self) -> dict[str, Any]:
        return {
            "message": self.message,
            "matched": self.matched,
            "matchedKeywords": self.matched_keywords,
            "matchedPatterns": self.matched_patterns,
            "matchType": self.match_type,
            "priority": self.priority,
            "priorityRank": self.priority_rank,
            "conflictRules": self.conflict_rules,
            "reason": self.reason,
        }


@dataclass
class IntentRuleTestResult:
    """Result of testing multiple messages against a rule."""

    rule_id: str
    rule_name: str
    results: list[IntentRuleTestCase]
    summary: dict[str, Any]

    def to_dict(self) -> dict[str, Any]:
        return {
            "ruleId": self.rule_id,
            "ruleName": self.rule_name,
            "results": [r.to_dict() for r in self.results],
            "summary": self.summary,
        }


class IntentRuleTester:
    """
    [AC-AISVC-96] Intent rule testing service.

    Features:
    - Test single rule against multiple messages
    - Detect priority conflicts (other rules that also match)
    - Provide detailed match information
    """

    def __init__(self):
        self._router = IntentRouter()

    async def test_rule(
        self,
        rule: IntentRule,
        test_messages: list[str],
        all_rules: list[IntentRule],
    ) -> IntentRuleTestResult:
        """
        Test a rule against multiple messages and detect conflicts.

        Args:
            rule: The rule to test
            test_messages: List of test messages
            all_rules: All rules for conflict detection (ordered by priority DESC)

        Returns:
            IntentRuleTestResult with detailed test results
        """
        results = []
        priority_rank = self._calculate_priority_rank(rule, all_rules)

        for message in test_messages:
            test_case = self._test_single_message(rule, message, all_rules, priority_rank)
            results.append(test_case)

        matched_count = sum(1 for r in results if r.matched)
        summary = {
            "totalTests": len(test_messages),
            "matchedCount": matched_count,
            "matchRate": matched_count / len(test_messages) if test_messages else 0,
        }

        logger.info(
            f"[AC-AISVC-96] Tested rule {rule.name}: "
            f"{matched_count}/{len(test_messages)} matched"
        )

        return IntentRuleTestResult(
            rule_id=str(rule.id),
            rule_name=rule.name,
            results=results,
            summary=summary,
        )

    def _test_single_message(
        self,
        rule: IntentRule,
        message: str,
        all_rules: list[IntentRule],
        priority_rank: int,
    ) -> IntentRuleTestCase:
        """Test a single message against a rule."""
        matched_keywords = self._match_keywords(message, rule)
        matched_patterns = self._match_patterns(message, rule)

        matched = len(matched_keywords) > 0 or len(matched_patterns) > 0
        match_type = None
        reason = None

        if matched:
            if matched_keywords:
                match_type = "keyword"
            else:
                match_type = "regex"
        else:
            reason = self._determine_unmatch_reason(message, rule)

        conflict_rules = self._detect_conflicts(rule, message, all_rules)

        return IntentRuleTestCase(
            message=message,
            matched=matched,
            matched_keywords=matched_keywords,
            matched_patterns=matched_patterns,
            match_type=match_type,
            priority=rule.priority,
            priority_rank=priority_rank,
            conflict_rules=conflict_rules,
            reason=reason,
        )

    def _match_keywords(self, message: str, rule: IntentRule) -> list[str]:
        """Match message against rule keywords."""
        matched = []
        keywords = rule.keywords or []
        message_lower = message.lower()

        for keyword in keywords:
            if keyword and keyword.lower() in message_lower:
                matched.append(keyword)

        return matched

    def _match_patterns(self, message: str, rule: IntentRule) -> list[str]:
        """Match message against rule regex patterns."""
        matched = []
        patterns = rule.patterns or []

        for pattern in patterns:
            if not pattern:
                continue
            try:
                if re.search(pattern, message, re.IGNORECASE):
                    matched.append(pattern)
            except re.error as e:
                logger.warning(f"Invalid regex pattern: {pattern}, error: {e}")

        return matched

    def _detect_conflicts(
        self,
        current_rule: IntentRule,
        message: str,
        all_rules: list[IntentRule],
    ) -> list[dict[str, Any]]:
        """Detect other rules that also match the message (priority conflicts)."""
        conflicts = []

        for other_rule in all_rules:
            if str(other_rule.id) == str(current_rule.id):
                continue

            if not other_rule.is_enabled:
                continue

            matched_keywords = self._match_keywords(message, other_rule)
            matched_patterns = self._match_patterns(message, other_rule)

            if matched_keywords or matched_patterns:
                conflicts.append({
                    "ruleId": str(other_rule.id),
                    "ruleName": other_rule.name,
                    "priority": other_rule.priority,
                    "reason": f"同时匹配（优先级：{other_rule.priority}）",
                })

        return conflicts

    def _calculate_priority_rank(
        self,
        rule: IntentRule,
        all_rules: list[IntentRule],
    ) -> int:
        """Calculate the priority rank of a rule among all rules."""
        enabled_rules = [r for r in all_rules if r.is_enabled]
        sorted_rules = sorted(enabled_rules, key=lambda r: r.priority, reverse=True)

        for rank, r in enumerate(sorted_rules, start=1):
            if str(r.id) == str(rule.id):
                return rank

        return 0

    def _determine_unmatch_reason(self, message: str, rule: IntentRule) -> str:
        """Determine why a message did not match a rule."""
        keywords = rule.keywords or []
        patterns = rule.patterns or []

        if not keywords and not patterns:
            return "规则未配置关键词或正则表达式"

        if keywords:
            keyword_str = "、".join(keywords[:3])
            if len(keywords) > 3:
                keyword_str += f"等{len(keywords)}个"
            return f"关键词不匹配（规则关键词：{keyword_str}）"

        if patterns:
            return f"正则表达式不匹配（规则模式：{len(patterns)}个）"

        return "未匹配"
