"""
Classification validator for post-LLM validation.

Catches common misclassification patterns based on keyword detection
and suggests corrections before persisting to database.
"""

from __future__ import annotations

import logging
import re
from typing import Any

logger = logging.getLogger(__name__)

# Price/money indicators → should be V codes
PRICE_PATTERNS = [
    r'\b\d+\s*[€$£]\b',  # "50€", "100$"
    r'\b[€$£]\s*\d+\b',  # "€50", "$100"
    r'\beur(o|os)?\b',
    r'\bprice[sd]?\b',
    r'\bcost[s]?\b',
    r'\bfee[s]?\b',
    r'\bcharge[sd]?\b',
    r'\bdeposit[s]?\b',
    r'\brefund[s]?\b',
    r'\bcheap\b',
    r'\bexpensive\b',
    r'\baffordable\b',
    r'\bpreis\b',  # German
    r'\bprecio[s]?\b',  # Spanish
    r'\bgünstig\b',  # German "cheap"
    r'\bteuer\b',  # German "expensive"
    r'\bbarato\b',  # Spanish "cheap"
    r'\bcaro\b',  # Spanish "expensive"
]

# Staff behavior indicators → should be P codes
STAFF_PATTERNS = [
    r'\bfriendly\b',
    r'\brude\b',
    r'\bhelpful\b',
    r'\bpatient\b',
    r'\bimpatient\b',
    r'\bwelcoming\b',
    r'\battentive\b',
    r'\bprofessional\b',
    r'\bunprofessional\b',
    r'\bamable\b',  # Spanish "friendly"
    r'\bsimpático\b',  # Spanish
    r'\bmuy amable\b',
    r'\bnett\b',  # German "nice"
    r'\bfreundlich\b',  # German "friendly"
    r'\bunfreundlich\b',  # German "unfriendly"
    r'\bgentil\b',  # French/Spanish
]

# Scam/ethics indicators → should be R codes
ETHICS_PATTERNS = [
    r'\bscam\b',
    r'\bfraud\b',
    r'\bcheat\b',
    r'\bdishonest\b',
    r'\blied\b',
    r'\blie[s]?\b',
    r'\bscammer[s]?\b',
    r'\bsteal\b',
    r'\bstole\b',
    r'\brobber[y]?\b',
    r'\bestafa\b',  # Spanish "scam"
    r'\btramp[a]?\b',  # Spanish "trap/trick"
    r'\bengaño\b',  # Spanish "deception"
    r'\bAbzocker\b',  # German "rip-off"
    r'\bBetrug\b',  # German "fraud"
    r'\barnaque\b',  # French "scam"
    r'\bvoleur[s]?\b',  # French "thief"
]

# Wayfinding indicators → should be A1.04
WAYFINDING_PATTERNS = [
    r"\bcouldn'?t find\b",
    r'\bhard to find\b',
    r'\bdifficult to find\b',
    r'\bconfusing\b.*\b(direction|location|shuttle)\b',
    r'\blost\b',
    r'\bno signs?\b',
    r'\bno señal\b',  # Spanish
    r'\bkeine Schilder\b',  # German
]


def validate_classification(
    span_text: str,
    urt_code: str,
    valence: str,
) -> dict[str, Any] | None:
    """
    Validate a classification and suggest correction if needed.

    Args:
        span_text: The span text
        urt_code: The assigned URT code
        valence: The assigned valence

    Returns:
        Correction dict if misclassified, None if OK
    """
    text_lower = span_text.lower()
    domain = urt_code[0]  # First letter is domain

    # Rule 1: Price mentions should be V codes
    if domain != 'V':
        for pattern in PRICE_PATTERNS:
            if re.search(pattern, text_lower, re.IGNORECASE):
                # Determine which V code
                if any(re.search(p, text_lower, re.I) for p in [r'hidden', r'extra', r'surprise', r'unexpected', r'trampa']):
                    suggested = 'V1.03'
                elif any(re.search(p, text_lower, re.I) for p in [r'overcharge', r'wrong.*charge', r'billing']):
                    suggested = 'V4.04'
                else:
                    suggested = 'V1.01'

                logger.debug(f"Validation: {urt_code} → {suggested} (price mention)")
                return {
                    'suggested_urt': suggested,
                    'reason': 'price_mention',
                    'pattern': pattern,
                }

    # Rule 2: Staff behavior should be P codes
    if domain != 'P':
        for pattern in STAFF_PATTERNS:
            if re.search(pattern, text_lower, re.IGNORECASE):
                # Determine which P code
                if any(re.search(p, text_lower, re.I) for p in [r'rude', r'unfriendly', r'disrespect', r'unfreundlich']):
                    suggested = 'P1.02'
                elif any(re.search(p, text_lower, re.I) for p in [r'impatient', r'rushed']):
                    suggested = 'P1.03'
                else:
                    suggested = 'P1.01'

                logger.debug(f"Validation: {urt_code} → {suggested} (staff behavior)")
                return {
                    'suggested_urt': suggested,
                    'reason': 'staff_behavior',
                    'pattern': pattern,
                }

    # Rule 3: Scam/ethics should be R codes
    if domain != 'R':
        for pattern in ETHICS_PATTERNS:
            if re.search(pattern, text_lower, re.IGNORECASE):
                if any(re.search(p, text_lower, re.I) for p in [r'scam', r'fraud', r'cheat', r'estafa', r'Betrug', r'arnaque']):
                    suggested = 'R1.02'
                else:
                    suggested = 'R1.01'

                logger.debug(f"Validation: {urt_code} → {suggested} (ethics issue)")
                return {
                    'suggested_urt': suggested,
                    'reason': 'ethics_issue',
                    'pattern': pattern,
                }

    # Rule 4: Wayfinding should be A1.04
    if urt_code not in ('A1.04', 'A4.01'):
        for pattern in WAYFINDING_PATTERNS:
            if re.search(pattern, text_lower, re.IGNORECASE):
                logger.debug(f"Validation: {urt_code} → A1.04 (wayfinding)")
                return {
                    'suggested_urt': 'A1.04',
                    'reason': 'wayfinding',
                    'pattern': pattern,
                }

    return None  # Classification looks OK


def validate_and_fix_spans(spans: list[dict[str, Any]]) -> list[dict[str, Any]]:
    """
    Validate and fix a list of spans.

    Args:
        spans: List of span dicts with 'span_text', 'urt_primary', 'valence'

    Returns:
        List of spans with corrections applied
    """
    corrections_made = 0

    for span in spans:
        correction = validate_classification(
            span.get('span_text', ''),
            span.get('urt_primary', 'O1.01'),
            span.get('valence', 'V0'),
        )

        if correction:
            original = span['urt_primary']
            span['urt_primary'] = correction['suggested_urt']
            span['_validation_correction'] = {
                'original': original,
                'reason': correction['reason'],
            }
            corrections_made += 1

    if corrections_made:
        logger.info(f"Validation corrected {corrections_made} spans")

    return spans
