"""Service name normalization and mapping to maintenance subtypes."""
import re
from dataclasses import dataclass
from typing import Optional


@dataclass
class ServiceMapping:
    """Mapping result from extracted text to maintenance subtypes."""

    normalized_name: str  # Standardized service name
    subtypes: list[str]  # Maintenance subtypes from the system
    category: str  # routine_maintenance, repair, performance_upgrade
    confidence: float


# Maintenance subtypes from the system (must match exactly)
ROUTINE_MAINTENANCE_SUBTYPES = [
    "Accelerator Pedal",
    "Air Filter Element",
    "Brakes and Traction Control",
    "Cabin Air Filter / Purifier",
    "Coolant",
    "Doors",
    "Drive Belt",
    "Engine Oil",
    "Evaporative Emissions System",
    "Exhaust System",
    "Fluid - A/T",
    "Fluid - Differential",
    "Fluid - M/T",
    "Fluid Filter - A/T",
    "Fluids",
    "Fuel Delivery and Air Induction",
    "Hood Shock / Support",
    "Neutral Safety Switch",
    "Parking Brake System",
    "Restraints and Safety Systems",
    "Shift Interlock A/T",
    "Spark Plug",
    "Steering and Suspension",
    "Tires",
    "Trunk / Liftgate Shock / Support",
    "Washer Fluid",
    "Wiper Blade",
]


class ServiceMapper:
    """Map extracted service names to maintenance subtypes."""

    # Mapping from common service terms to system subtypes
    # Keys are lowercase patterns, values are (normalized_name, subtypes, category, confidence)
    SERVICE_MAPPINGS: dict[str, tuple[str, list[str], str, float]] = {
        # Oil related
        "engine oil": ("Engine Oil Change", ["Engine Oil"], "routine_maintenance", 0.95),
        "oil change": ("Engine Oil Change", ["Engine Oil"], "routine_maintenance", 0.95),
        "motor oil": ("Engine Oil Change", ["Engine Oil"], "routine_maintenance", 0.93),
        "oil and filter": ("Engine Oil Change", ["Engine Oil"], "routine_maintenance", 0.95),
        "oil & filter": ("Engine Oil Change", ["Engine Oil"], "routine_maintenance", 0.95),
        "change engine oil": ("Engine Oil Change", ["Engine Oil"], "routine_maintenance", 0.95),
        "replace engine oil": ("Engine Oil Change", ["Engine Oil"], "routine_maintenance", 0.95),
        # Air filter
        "air filter": ("Air Filter Replacement", ["Air Filter Element"], "routine_maintenance", 0.90),
        "engine air filter": ("Air Filter Replacement", ["Air Filter Element"], "routine_maintenance", 0.95),
        "air cleaner": ("Air Filter Replacement", ["Air Filter Element"], "routine_maintenance", 0.88),
        "air cleaner element": ("Air Filter Replacement", ["Air Filter Element"], "routine_maintenance", 0.93),
        "replace air filter": ("Air Filter Replacement", ["Air Filter Element"], "routine_maintenance", 0.95),
        # Cabin filter
        "cabin air filter": ("Cabin Air Filter Replacement", ["Cabin Air Filter / Purifier"], "routine_maintenance", 0.95),
        "cabin filter": ("Cabin Air Filter Replacement", ["Cabin Air Filter / Purifier"], "routine_maintenance", 0.93),
        "a/c filter": ("Cabin Air Filter Replacement", ["Cabin Air Filter / Purifier"], "routine_maintenance", 0.88),
        "hvac filter": ("Cabin Air Filter Replacement", ["Cabin Air Filter / Purifier"], "routine_maintenance", 0.88),
        "interior air filter": ("Cabin Air Filter Replacement", ["Cabin Air Filter / Purifier"], "routine_maintenance", 0.90),
        "dust and pollen filter": ("Cabin Air Filter Replacement", ["Cabin Air Filter / Purifier"], "routine_maintenance", 0.90),
        # Tires
        "tire rotation": ("Tire Rotation", ["Tires"], "routine_maintenance", 0.98),
        "rotate tires": ("Tire Rotation", ["Tires"], "routine_maintenance", 0.95),
        "tire inspection": ("Tire Inspection", ["Tires"], "routine_maintenance", 0.93),
        "inspect tires": ("Tire Inspection", ["Tires"], "routine_maintenance", 0.93),
        "check tire pressure": ("Tire Pressure Check", ["Tires"], "routine_maintenance", 0.90),
        "tire pressure": ("Tire Pressure Check", ["Tires"], "routine_maintenance", 0.85),
        # Brakes
        "brake inspection": ("Brake Inspection", ["Brakes and Traction Control"], "routine_maintenance", 0.95),
        "inspect brakes": ("Brake Inspection", ["Brakes and Traction Control"], "routine_maintenance", 0.93),
        "brake fluid": ("Brake Fluid Service", ["Brakes and Traction Control"], "routine_maintenance", 0.93),
        "brake pads": ("Brake Pad Inspection", ["Brakes and Traction Control"], "routine_maintenance", 0.90),
        "parking brake": ("Parking Brake Inspection", ["Parking Brake System"], "routine_maintenance", 0.93),
        # Coolant
        "coolant": ("Coolant Service", ["Coolant"], "routine_maintenance", 0.90),
        "engine coolant": ("Coolant Service", ["Coolant"], "routine_maintenance", 0.93),
        "antifreeze": ("Coolant Service", ["Coolant"], "routine_maintenance", 0.90),
        "cooling system": ("Coolant Service", ["Coolant"], "routine_maintenance", 0.88),
        "radiator fluid": ("Coolant Service", ["Coolant"], "routine_maintenance", 0.88),
        "replace coolant": ("Coolant Replacement", ["Coolant"], "routine_maintenance", 0.95),
        # Transmission
        "transmission fluid": ("Transmission Fluid Service", ["Fluid - A/T"], "routine_maintenance", 0.93),
        "automatic transmission fluid": ("Transmission Fluid Service", ["Fluid - A/T"], "routine_maintenance", 0.95),
        "atf": ("Transmission Fluid Service", ["Fluid - A/T"], "routine_maintenance", 0.90),
        "manual transmission fluid": ("Manual Transmission Fluid", ["Fluid - M/T"], "routine_maintenance", 0.95),
        "cvt fluid": ("CVT Fluid Service", ["Fluid - A/T"], "routine_maintenance", 0.93),
        "transmission filter": ("Transmission Filter", ["Fluid Filter - A/T"], "routine_maintenance", 0.93),
        # Differential
        "differential fluid": ("Differential Fluid Service", ["Fluid - Differential"], "routine_maintenance", 0.95),
        "rear differential": ("Differential Fluid Service", ["Fluid - Differential"], "routine_maintenance", 0.93),
        "front differential": ("Differential Fluid Service", ["Fluid - Differential"], "routine_maintenance", 0.93),
        "transfer case": ("Transfer Case Fluid", ["Fluid - Differential"], "routine_maintenance", 0.90),
        # Spark plugs
        "spark plug": ("Spark Plug Replacement", ["Spark Plug"], "routine_maintenance", 0.95),
        "spark plugs": ("Spark Plug Replacement", ["Spark Plug"], "routine_maintenance", 0.95),
        "replace spark plugs": ("Spark Plug Replacement", ["Spark Plug"], "routine_maintenance", 0.95),
        "ignition plugs": ("Spark Plug Replacement", ["Spark Plug"], "routine_maintenance", 0.88),
        # Drive belt
        "drive belt": ("Drive Belt Inspection", ["Drive Belt"], "routine_maintenance", 0.93),
        "serpentine belt": ("Drive Belt Inspection", ["Drive Belt"], "routine_maintenance", 0.93),
        "accessory belt": ("Drive Belt Inspection", ["Drive Belt"], "routine_maintenance", 0.90),
        "timing belt": ("Timing Belt Service", ["Drive Belt"], "routine_maintenance", 0.90),
        "v-belt": ("Drive Belt Inspection", ["Drive Belt"], "routine_maintenance", 0.88),
        # Wipers
        "wiper blade": ("Wiper Blade Replacement", ["Wiper Blade"], "routine_maintenance", 0.95),
        "wiper blades": ("Wiper Blade Replacement", ["Wiper Blade"], "routine_maintenance", 0.95),
        "windshield wiper": ("Wiper Blade Replacement", ["Wiper Blade"], "routine_maintenance", 0.93),
        "replace wipers": ("Wiper Blade Replacement", ["Wiper Blade"], "routine_maintenance", 0.93),
        # Washer fluid
        "washer fluid": ("Washer Fluid", ["Washer Fluid"], "routine_maintenance", 0.95),
        "windshield washer": ("Washer Fluid", ["Washer Fluid"], "routine_maintenance", 0.90),
        # Steering/Suspension
        "steering": ("Steering Inspection", ["Steering and Suspension"], "routine_maintenance", 0.85),
        "suspension": ("Suspension Inspection", ["Steering and Suspension"], "routine_maintenance", 0.85),
        "power steering": ("Power Steering Fluid", ["Steering and Suspension"], "routine_maintenance", 0.90),
        "power steering fluid": ("Power Steering Fluid", ["Steering and Suspension"], "routine_maintenance", 0.93),
        # Exhaust
        "exhaust": ("Exhaust System Inspection", ["Exhaust System"], "routine_maintenance", 0.88),
        "exhaust system": ("Exhaust System Inspection", ["Exhaust System"], "routine_maintenance", 0.93),
        # Fuel system
        "fuel filter": ("Fuel Filter Replacement", ["Fuel Delivery and Air Induction"], "routine_maintenance", 0.93),
        "fuel system": ("Fuel System Inspection", ["Fuel Delivery and Air Induction"], "routine_maintenance", 0.88),
        "fuel injection": ("Fuel Injection Service", ["Fuel Delivery and Air Induction"], "routine_maintenance", 0.88),
        # Emissions
        "evaporative emissions": ("Evaporative Emissions Inspection", ["Evaporative Emissions System"], "routine_maintenance", 0.93),
        "evap system": ("Evaporative Emissions Inspection", ["Evaporative Emissions System"], "routine_maintenance", 0.90),
        "emissions": ("Evaporative Emissions Inspection", ["Evaporative Emissions System"], "routine_maintenance", 0.80),
        # Safety systems
        "seat belt": ("Safety Systems Inspection", ["Restraints and Safety Systems"], "routine_maintenance", 0.90),
        "airbag": ("Safety Systems Inspection", ["Restraints and Safety Systems"], "routine_maintenance", 0.85),
        "restraint": ("Safety Systems Inspection", ["Restraints and Safety Systems"], "routine_maintenance", 0.85),
        # Miscellaneous
        "battery": ("Battery Inspection", ["Fluids"], "routine_maintenance", 0.80),
        "inspect battery": ("Battery Inspection", ["Fluids"], "routine_maintenance", 0.85),
        "door hinges": ("Door Lubrication", ["Doors"], "routine_maintenance", 0.85),
        "hood shock": ("Hood Shock Inspection", ["Hood Shock / Support"], "routine_maintenance", 0.90),
        "trunk shock": ("Trunk Shock Inspection", ["Trunk / Liftgate Shock / Support"], "routine_maintenance", 0.90),
        "liftgate": ("Liftgate Inspection", ["Trunk / Liftgate Shock / Support"], "routine_maintenance", 0.88),
    }

    # Pattern-based mappings for fuzzy matching
    SERVICE_PATTERNS: list[tuple[str, str, list[str], str, float]] = [
        # (regex_pattern, normalized_name, subtypes, category, confidence)
        (r"oil\s+(?:and|&)\s+filter", "Engine Oil Change", ["Engine Oil"], "routine_maintenance", 0.95),
        (r"(?:change|replace)\s+(?:the\s+)?oil", "Engine Oil Change", ["Engine Oil"], "routine_maintenance", 0.93),
        (r"(?:inspect|check)\s+(?:the\s+)?brakes?", "Brake Inspection", ["Brakes and Traction Control"], "routine_maintenance", 0.90),
        (r"(?:inspect|check)\s+(?:the\s+)?tires?", "Tire Inspection", ["Tires"], "routine_maintenance", 0.90),
        (r"(?:rotate|rotation)\s+(?:the\s+)?tires?", "Tire Rotation", ["Tires"], "routine_maintenance", 0.95),
        (r"(?:replace|change)\s+(?:the\s+)?(?:engine\s+)?air\s+filter", "Air Filter Replacement", ["Air Filter Element"], "routine_maintenance", 0.95),
        (r"(?:replace|change)\s+(?:the\s+)?cabin\s+(?:air\s+)?filter", "Cabin Air Filter Replacement", ["Cabin Air Filter / Purifier"], "routine_maintenance", 0.95),
        (r"(?:replace|change)\s+(?:the\s+)?spark\s+plugs?", "Spark Plug Replacement", ["Spark Plug"], "routine_maintenance", 0.95),
        (r"(?:replace|change)\s+(?:the\s+)?coolant", "Coolant Replacement", ["Coolant"], "routine_maintenance", 0.93),
        (r"(?:flush|drain)\s+(?:the\s+)?coolant", "Coolant Flush", ["Coolant"], "routine_maintenance", 0.93),
        (r"(?:replace|change)\s+(?:the\s+)?(?:a/?t|automatic\s+transmission)\s+fluid", "Transmission Fluid Service", ["Fluid - A/T"], "routine_maintenance", 0.93),
        (r"(?:inspect|check)\s+(?:the\s+)?(?:drive|serpentine|accessory)\s+belt", "Drive Belt Inspection", ["Drive Belt"], "routine_maintenance", 0.90),
    ]

    def map_service(self, service_text: str) -> Optional[ServiceMapping]:
        """
        Map extracted service text to maintenance subtypes.

        Args:
            service_text: Service name or description from the manual

        Returns:
            ServiceMapping or None if no mapping found
        """
        normalized_text = service_text.lower().strip()

        # Try exact mapping first
        for key, (name, subtypes, category, conf) in self.SERVICE_MAPPINGS.items():
            if key in normalized_text:
                return ServiceMapping(
                    normalized_name=name,
                    subtypes=subtypes,
                    category=category,
                    confidence=conf,
                )

        # Try pattern matching
        for pattern, name, subtypes, category, conf in self.SERVICE_PATTERNS:
            if re.search(pattern, normalized_text, re.IGNORECASE):
                return ServiceMapping(
                    normalized_name=name,
                    subtypes=subtypes,
                    category=category,
                    confidence=conf,
                )

        return None

    def map_service_fuzzy(self, service_text: str, threshold: float = 0.6) -> Optional[ServiceMapping]:
        """
        Map service text with fuzzy matching for typos and variations.

        Args:
            service_text: Service name or description
            threshold: Minimum similarity threshold (0.0-1.0)

        Returns:
            ServiceMapping or None
        """
        # First try exact matching
        result = self.map_service(service_text)
        if result:
            return result

        # Fall back to word overlap matching
        words = set(service_text.lower().split())

        best_match: Optional[ServiceMapping] = None
        best_score = 0.0

        for key, (name, subtypes, category, conf) in self.SERVICE_MAPPINGS.items():
            key_words = set(key.split())
            overlap = len(words & key_words)
            total = len(words | key_words)

            if total > 0:
                score = overlap / total
                if score > best_score and score >= threshold:
                    best_score = score
                    best_match = ServiceMapping(
                        normalized_name=name,
                        subtypes=subtypes,
                        category=category,
                        confidence=conf * score,  # Reduce confidence by match quality
                    )

        return best_match

    def get_all_service_keywords(self) -> list[str]:
        """Get all service keywords for table header detection."""
        keywords = list(self.SERVICE_MAPPINGS.keys())
        # Add common header terms
        keywords.extend([
            "service", "maintenance", "item", "operation",
            "inspection", "replacement", "interval", "schedule",
        ])
        return keywords


# Singleton instance
service_mapper = ServiceMapper()
