"""
OCPP Event handlers for WebSocket server
Standalone WebSocket-specific handlers
"""
import asyncio
import logging
from datetime import datetime, timezone
from typing import Dict, List, Callable, Any

logger = logging.getLogger(__name__)


# WebSocket-specific OCPP Event Handlers

async def handle_boot_notification(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle BootNotification - WebSocket version with charge point registration"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    
    # WebSocket server implementation
    response = {
        "status": "Accepted",
        "currentTime": datetime.now(timezone.utc).isoformat(),
        "interval": 300
    }
    
    logger.info(f"[WS] BootNotification from {charge_point_id}: {response['status']}")
    return response


async def handle_heartbeat(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle Heartbeat - Simple response with current time"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    
    response = {
        "currentTime": datetime.now(timezone.utc).isoformat()
    }
    
    logger.debug(f"[WS] Heartbeat from {charge_point_id}")
    return response


async def handle_start_transaction(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle StartTransaction - WebSocket version with transaction tracking"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    connector_id = payload.get("connectorId", 1)
    id_tag = payload.get("idTag", "unknown")
    
    # Generate a simple transaction ID
    import time
    transaction_id = int(time.time() * 1000)
    
    response = {
        "transactionId": transaction_id,
        "idTagInfo": {
            "status": "Accepted"
        }
    }
    
    logger.info(f"[WS] StartTransaction from {charge_point_id}, connector {connector_id}, tag {id_tag}: transaction {transaction_id}")
    return response


async def handle_stop_transaction(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle StopTransaction - WebSocket version"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    transaction_id = payload.get("transactionId", "unknown")
    
    response = {
        "idTagInfo": {
            "status": "Accepted"
        }
    }
    
    logger.info(f"[WS] StopTransaction from {charge_point_id}: transaction {transaction_id}")
    return response


async def handle_status_notification(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle StatusNotification - WebSocket version with status tracking"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    connector_id = payload.get("connectorId", 0)
    status = payload.get("status", "Unknown")
    error_code = payload.get("errorCode", "NoError")
    
    logger.info(f"[WS] StatusNotification from {charge_point_id}, connector {connector_id}: {status} ({error_code})")
    
    # Status notifications don't typically require a response
    return {}


async def handle_meter_values(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle MeterValues - WebSocket version with value logging"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    connector_id = payload.get("connectorId", 0)
    transaction_id = payload.get("transactionId")
    meter_value = payload.get("meterValue", [])
    
    logger.info(f"[WS] MeterValues from {charge_point_id}, connector {connector_id}, transaction {transaction_id}: {len(meter_value)} values")
    
    # MeterValues don't typically require a response
    return {}


async def handle_authorize(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle Authorize - Simple authorization"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    id_tag = payload.get("idTag", "unknown")
    
    response = {
        "idTagInfo": {
            "status": "Accepted"
        }
    }
    
    logger.info(f"[WS] Authorize from {charge_point_id}, tag {id_tag}: {response['idTagInfo']['status']}")
    return response


async def handle_data_transfer(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle DataTransfer - Generic data transfer"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    vendor_id = payload.get("vendorId", "unknown")
    message_id = payload.get("messageId", "")
    data = payload.get("data", "")
    
    response = {
        "status": "Accepted"
    }
    
    logger.info(f"[WS] DataTransfer from {charge_point_id}, vendor {vendor_id}, message {message_id}")
    return response


async def handle_firmware_status_notification(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle FirmwareStatusNotification"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    status = payload.get("status", "Unknown")
    
    logger.info(f"[WS] FirmwareStatusNotification from {charge_point_id}: {status}")
    return {}


async def handle_diagnostic_status_notification(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle DiagnosticsStatusNotification"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    status = payload.get("status", "Unknown")
    
    logger.info(f"[WS] DiagnosticsStatusNotification from {charge_point_id}: {status}")
    return {}


# OCPP 1.6 Additional Event Handlers

async def handle_pause_transaction(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle PauseTransaction - Temporarily pause an active charging session"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    transaction_id = payload.get("transactionId")
    reason = payload.get("reason", "UserRequest")
    
    logger.info(f"[WS] Pausing transaction {transaction_id} from {charge_point_id}, reason: {reason}")
    
    return {
        "status": "Accepted"
    }

async def handle_resume_transaction(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle ResumeTransaction - Resume a paused charging session"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    transaction_id = payload.get("transactionId")
    
    logger.info(f"[WS] Resuming transaction {transaction_id} from {charge_point_id}")
    
    return {
        "status": "Accepted"
    }

async def handle_change_availability(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle ChangeAvailability - Central System to Charge Point"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    connector_id = payload.get("connectorId", 0)
    availability_type = payload.get("type", "Operative")
    
    response = {
        "status": "Accepted"
    }
    
    logger.info(f"[WS] ChangeAvailability to {charge_point_id}, connector {connector_id}: {availability_type}")
    return response


async def handle_get_configuration(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle GetConfiguration - Return configuration keys"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    keys = payload.get("key", [])
    
    # Mock configuration values
    config_values = {
        "HeartbeatInterval": "300",
        "MeterValueSampleInterval": "60",
        "ClockAlignedDataInterval": "0",
        "MeterValuesAlignedData": "Energy.Active.Import.Register",
        "StopTxnAlignedData": "",
        "StopTxnSampledData": "",
        "SupportedFeatureProfiles": "Core,FirmwareManagement,LocalAuthListManagement,Reservation,SmartCharging",
        "ChargeProfileMaxStackLevel": "10",
        "ChargingScheduleMaxPeriods": "10",
        "MaxChargingProfilesInstalled": "10"
    }
    
    if not keys:  # Return all configuration
        keys = list(config_values.keys())
    
    configuration_key = []
    unknown_key = []
    
    for key in keys:
        if key in config_values:
            configuration_key.append({
                "key": key,
                "readonly": False,
                "value": config_values[key]
            })
        else:
            unknown_key.append(key)
    
    response = {
        "configurationKey": configuration_key
    }
    
    if unknown_key:
        response["unknownKey"] = unknown_key
    
    logger.info(f"[WS] GetConfiguration from {charge_point_id}: {len(configuration_key)} keys")
    return response


async def handle_change_configuration(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle ChangeConfiguration - Change configuration parameter"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    key = payload.get("key", "")
    value = payload.get("value", "")
    
    # Mock acceptance of configuration changes
    response = {
        "status": "Accepted"
    }
    
    logger.info(f"[WS] ChangeConfiguration from {charge_point_id}: {key} = {value}")
    return response


async def handle_clear_cache(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle ClearCache - Clear local authorization cache"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    
    response = {
        "status": "Accepted"
    }
    
    logger.info(f"[WS] ClearCache from {charge_point_id}")
    return response


async def handle_remote_start_transaction(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle RemoteStartTransaction - Start transaction remotely"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    connector_id = payload.get("connectorId", 1)
    id_tag = payload.get("idTag", "")
    
    response = {
        "status": "Accepted"
    }
    
    logger.info(f"[WS] RemoteStartTransaction to {charge_point_id}, connector {connector_id}, tag {id_tag}")
    return response


async def handle_remote_stop_transaction(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle RemoteStopTransaction - Stop transaction remotely"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    transaction_id = payload.get("transactionId", 0)
    
    response = {
        "status": "Accepted"
    }
    
    logger.info(f"[WS] RemoteStopTransaction to {charge_point_id}, transaction {transaction_id}")
    return response


async def handle_reset(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle Reset - Reset charge point"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    reset_type = payload.get("type", "Soft")
    
    response = {
        "status": "Accepted"
    }
    
    logger.info(f"[WS] Reset {reset_type} to {charge_point_id}")
    return response


async def handle_unlock_connector(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle UnlockConnector - Unlock specific connector"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    connector_id = payload.get("connectorId", 1)
    
    response = {
        "status": "Unlocked"  # Could also be "UnlockFailed" or "NotSupported"
    }
    
    logger.info(f"[WS] UnlockConnector to {charge_point_id}, connector {connector_id}")
    return response


async def handle_trigger_message(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle TriggerMessage - Request specific message from charge point"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    requested_message = payload.get("requestedMessage", "")
    connector_id = payload.get("connectorId")
    
    response = {
        "status": "Accepted"
    }
    
    logger.info(f"[WS] TriggerMessage to {charge_point_id}: {requested_message}" + 
                (f" (connector {connector_id})" if connector_id else ""))
    return response


async def handle_update_firmware(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle UpdateFirmware - Update firmware"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    location = payload.get("location", "")
    retrieve_date = payload.get("retrieveDate", "")
    
    response = {}  # UpdateFirmware typically has no response payload
    
    logger.info(f"[WS] UpdateFirmware to {charge_point_id}: {location} at {retrieve_date}")
    return response


async def handle_get_diagnostics(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle GetDiagnostics - Request diagnostics upload"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    location = payload.get("location", "")
    
    response = {
        "fileName": f"diagnostics_{charge_point_id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"
    }
    
    logger.info(f"[WS] GetDiagnostics to {charge_point_id}: upload to {location}")
    return response


async def handle_get_local_list_version(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle GetLocalListVersion - Get local authorization list version"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    
    response = {
        "listVersion": 1  # Mock version number
    }
    
    logger.info(f"[WS] GetLocalListVersion from {charge_point_id}: version {response['listVersion']}")
    return response


async def handle_send_local_list(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle SendLocalList - Send local authorization list"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    list_version = payload.get("listVersion", 0)
    update_type = payload.get("updateType", "Full")
    
    response = {
        "status": "Accepted"
    }
    
    logger.info(f"[WS] SendLocalList to {charge_point_id}: version {list_version}, type {update_type}")
    return response


async def handle_set_charging_profile(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle SetChargingProfile - Set charging profile"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    connector_id = payload.get("connectorId", 0)
    cs_charging_profiles = payload.get("csChargingProfiles", {})
    
    response = {
        "status": "Accepted"
    }
    
    logger.info(f"[WS] SetChargingProfile to {charge_point_id}, connector {connector_id}")
    return response


async def handle_clear_charging_profile(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle ClearChargingProfile - Clear charging profile"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    profile_id = payload.get("id")
    connector_id = payload.get("connectorId")
    
    response = {
        "status": "Accepted"
    }
    
    logger.info(f"[WS] ClearChargingProfile from {charge_point_id}" + 
                (f", profile {profile_id}" if profile_id else "") +
                (f", connector {connector_id}" if connector_id else ""))
    return response


async def handle_get_composite_schedule(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle GetCompositeSchedule - Get composite charging schedule"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    connector_id = payload.get("connectorId", 1)
    duration = payload.get("duration", 3600)
    
    # Mock composite schedule
    response = {
        "status": "Accepted",
        "connectorId": connector_id,
        "scheduleStart": datetime.now(timezone.utc).isoformat(),
        "chargingSchedule": {
            "chargingRateUnit": "W",
            "chargingSchedulePeriod": [
                {
                    "startPeriod": 0,
                    "limit": 22000
                }
            ]
        }
    }
    
    logger.info(f"[WS] GetCompositeSchedule from {charge_point_id}, connector {connector_id}, duration {duration}s")
    return response


async def handle_reserve_now(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle ReserveNow - Reserve connector"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    connector_id = payload.get("connectorId", 1)
    expiry_date = payload.get("expiryDate", "")
    id_tag = payload.get("idTag", "")
    reservation_id = payload.get("reservationId", 0)
    
    response = {
        "status": "Accepted"
    }
    
    logger.info(f"[WS] ReserveNow to {charge_point_id}, connector {connector_id}, reservation {reservation_id}")
    return response


async def handle_cancel_reservation(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle CancelReservation - Cancel reservation"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    reservation_id = payload.get("reservationId", 0)
    
    response = {
        "status": "Accepted"
    }
    
    logger.info(f"[WS] CancelReservation from {charge_point_id}, reservation {reservation_id}")
    return response


# OCPP 2.0.1 Event Handlers (Basic Support)

async def handle_transaction_event(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle TransactionEvent - OCPP 2.0.1"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    event_type = payload.get("eventType", "Unknown")
    transaction_info = payload.get("transactionInfo", {})
    
    response = {
        "totalCost": 0.0,
        "chargingPriority": 1,
        "idTokenInfo": {
            "status": "Accepted"
        }
    }
    
    logger.info(f"[WS] TransactionEvent from {charge_point_id}: {event_type}")
    return response


async def handle_notify_report(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle NotifyReport - OCPP 2.0.1"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    request_id = payload.get("requestId", 0)
    
    response = {}  # NotifyReport typically has no response
    
    logger.info(f"[WS] NotifyReport from {charge_point_id}: request {request_id}")
    return response


async def handle_notify_event(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle NotifyEvent - OCPP 2.0.1"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    generated_at = payload.get("generatedAt", "")
    seq_no = payload.get("seqNo", 0)
    
    response = {}  # NotifyEvent typically has no response
    
    logger.info(f"[WS] NotifyEvent from {charge_point_id}: seq {seq_no}")
    return response


async def handle_notify_charging_limit(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle NotifyChargingLimit - OCPP 2.0.1"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    charging_limit = payload.get("chargingLimit", {})
    
    response = {}  # NotifyChargingLimit typically has no response
    
    logger.info(f"[WS] NotifyChargingLimit from {charge_point_id}")
    return response


async def handle_log_status_notification(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle LogStatusNotification - OCPP 2.0.1"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    status = payload.get("status", "Unknown")
    request_id = payload.get("requestId", 0)
    
    response = {}  # LogStatusNotification typically has no response
    
    logger.info(f"[WS] LogStatusNotification from {charge_point_id}: {status} (req {request_id})")
    return response


async def handle_report_charging_profiles(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle ReportChargingProfiles - OCPP 2.0.1"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    request_id = payload.get("requestId", 0)
    
    response = {}  # ReportChargingProfiles typically has no response
    
    logger.info(f"[WS] ReportChargingProfiles from {charge_point_id}: request {request_id}")
    return response


# Additional OCPP 2.0.1 Event Handlers

async def handle_boot_notification_20(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle BootNotification - OCPP 2.0.1 version"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    charging_station = payload.get("chargingStation", {})
    reason = payload.get("reason", "PowerUp")
    
    response = {
        "currentTime": datetime.now(timezone.utc).isoformat(),
        "interval": 300,
        "status": "Accepted"
    }
    
    logger.info(f"[WS] BootNotification 2.0.1 from {charge_point_id}: {reason}")
    return response


async def handle_heartbeat_20(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle Heartbeat - OCPP 2.0.1 version"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    
    response = {
        "currentTime": datetime.now(timezone.utc).isoformat()
    }
    
    logger.debug(f"[WS] Heartbeat 2.0.1 from {charge_point_id}")
    return response


async def handle_status_notification_20(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle StatusNotification - OCPP 2.0.1 version"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    evse_id = payload.get("evseId", 1)
    connector_id = payload.get("connectorId", 1)
    connector_status = payload.get("connectorStatus", "Available")
    
    logger.info(f"[WS] StatusNotification 2.0.1 from {charge_point_id}, EVSE {evse_id}, connector {connector_id}: {connector_status}")
    
    return {}  # StatusNotification typically has no response


async def handle_authorize_20(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle Authorize - OCPP 2.0.1 version"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    id_token = payload.get("idToken", {})
    token_value = id_token.get("idToken", "unknown")
    token_type = id_token.get("type", "ISO14443")
    
    response = {
        "idTokenInfo": {
            "status": "Accepted"
        }
    }
    
    logger.info(f"[WS] Authorize 2.0.1 from {charge_point_id}, token: {token_value} ({token_type})")
    return response


async def handle_notify_customer_information(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle NotifyCustomerInformation - OCPP 2.0.1"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    request_id = payload.get("requestId", 0)
    data = payload.get("data", "")
    
    logger.info(f"[WS] NotifyCustomerInformation from {charge_point_id}: request {request_id}")
    return {}


async def handle_notify_display_messages(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle NotifyDisplayMessages - OCPP 2.0.1"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    request_id = payload.get("requestId", 0)
    message_info = payload.get("messageInfo", [])
    
    logger.info(f"[WS] NotifyDisplayMessages from {charge_point_id}: request {request_id}, {len(message_info)} messages")
    return {}


async def handle_notify_ev_charging_needs(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle NotifyEVChargingNeeds - OCPP 2.0.1"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    evse_id = payload.get("evseId", 1)
    charging_needs = payload.get("chargingNeeds", {})
    
    response = {
        "status": "Accepted"
    }
    
    logger.info(f"[WS] NotifyEVChargingNeeds from {charge_point_id}, EVSE {evse_id}")
    return response


async def handle_notify_ev_charging_schedule(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle NotifyEVChargingSchedule - OCPP 2.0.1"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    evse_id = payload.get("evseId", 1)
    time_base = payload.get("timeBase", "")
    
    response = {
        "status": "Accepted"
    }
    
    logger.info(f"[WS] NotifyEVChargingSchedule from {charge_point_id}, EVSE {evse_id}")
    return response


async def handle_publish_firmware_status_notification(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle PublishFirmwareStatusNotification - OCPP 2.0.1"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    status = payload.get("status", "Unknown")
    request_id = payload.get("requestId", 0)
    
    logger.info(f"[WS] PublishFirmwareStatusNotification from {charge_point_id}: {status} (req {request_id})")
    return {}


async def handle_reservation_status_update(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle ReservationStatusUpdate - OCPP 2.0.1"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    reservation_id = payload.get("reservationId", 0)
    status = payload.get("reservationUpdateStatus", "Unknown")
    
    logger.info(f"[WS] ReservationStatusUpdate from {charge_point_id}: reservation {reservation_id} -> {status}")
    return {}


async def handle_security_event_notification(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle SecurityEventNotification - OCPP 2.0.1"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    event_type = payload.get("type", "Unknown")
    timestamp = payload.get("timestamp", "")
    tech_info = payload.get("techInfo", "")
    
    logger.info(f"[WS] SecurityEventNotification from {charge_point_id}: {event_type} at {timestamp}")
    return {}


async def handle_sign_certificate(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle SignCertificate - OCPP 2.0.1"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    csr = payload.get("csr", "")
    certificate_type = payload.get("certificateType", "ChargingStationCertificate")
    
    response = {
        "status": "Accepted"
    }
    
    logger.info(f"[WS] SignCertificate from {charge_point_id}: {certificate_type}")
    return response


async def handle_data_transfer_20(payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle DataTransfer - OCPP 2.0.1 version"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    vendor_id = payload.get("vendorId", "unknown")
    message_id = payload.get("messageId", "")
    data = payload.get("data", {})
    
    response = {
        "status": "Accepted"
    }
    
    logger.info(f"[WS] DataTransfer 2.0.1 from {charge_point_id}, vendor {vendor_id}, message {message_id}")
    return response


async def handle_unknown_event(action: str, payload: Dict[str, Any]) -> Dict[str, Any]:
    """Handle unknown/unsupported OCPP actions"""
    charge_point_id = payload.get("_charge_point_id", "unknown")
    
    logger.warning(f"[WS] Unknown action '{action}' from {charge_point_id}")
    return {
        "status": "NotSupported",
        "error": f"Action '{action}' is not supported by this server"
    }


# Event handler registry
def get_event_handlers() -> Dict[str, Callable]:
    """Get mapping of OCPP actions to their handler functions"""
    return {
        # OCPP 1.6 Core Events
        "BootNotification": handle_boot_notification,
        "Heartbeat": handle_heartbeat,
        "StartTransaction": handle_start_transaction,
        "StopTransaction": handle_stop_transaction,
        "StatusNotification": handle_status_notification,
        "MeterValues": handle_meter_values,
        "Authorize": handle_authorize,
        "DataTransfer": handle_data_transfer,
        "FirmwareStatusNotification": handle_firmware_status_notification,
        "DiagnosticsStatusNotification": handle_diagnostic_status_notification,
        "PauseTransaction": handle_pause_transaction,
        "ResumeTransaction": handle_resume_transaction,
        
        # OCPP 1.6 Remote Commands
        "ChangeAvailability": handle_change_availability,
        "GetConfiguration": handle_get_configuration,
        "ChangeConfiguration": handle_change_configuration,
        "ClearCache": handle_clear_cache,
        "RemoteStartTransaction": handle_remote_start_transaction,
        "RemoteStopTransaction": handle_remote_stop_transaction,
        "Reset": handle_reset,
        "UnlockConnector": handle_unlock_connector,
        "TriggerMessage": handle_trigger_message,
        "UpdateFirmware": handle_update_firmware,
        "GetDiagnostics": handle_get_diagnostics,
        
        # OCPP 1.6 Smart Charging & Local List Management
        "GetLocalListVersion": handle_get_local_list_version,
        "SendLocalList": handle_send_local_list,
        "SetChargingProfile": handle_set_charging_profile,
        "ClearChargingProfile": handle_clear_charging_profile,
        "GetCompositeSchedule": handle_get_composite_schedule,
        
        # OCPP 1.6 Reservations
        "ReserveNow": handle_reserve_now,
        "CancelReservation": handle_cancel_reservation,
        
        # OCPP 2.0.1 Events (Basic Support)
        "TransactionEvent": handle_transaction_event,
        "NotifyReport": handle_notify_report,
        "NotifyEvent": handle_notify_event,
        "NotifyChargingLimit": handle_notify_charging_limit,
        "LogStatusNotification": handle_log_status_notification,
        "ReportChargingProfiles": handle_report_charging_profiles,
        
        # Additional OCPP 2.0.1 Events
        "BootNotification20": handle_boot_notification_20,
        "Heartbeat20": handle_heartbeat_20,
        "StatusNotification20": handle_status_notification_20,
        "Authorize20": handle_authorize_20,
        "NotifyCustomerInformation": handle_notify_customer_information,
        "NotifyDisplayMessages": handle_notify_display_messages,
        "NotifyEVChargingNeeds": handle_notify_ev_charging_needs,
        "NotifyEVChargingSchedule": handle_notify_ev_charging_schedule,
        "PublishFirmwareStatusNotification": handle_publish_firmware_status_notification,
        "ReservationStatusUpdate": handle_reservation_status_update,
        "SecurityEventNotification": handle_security_event_notification,
        "SignCertificate": handle_sign_certificate,
        "DataTransfer20": handle_data_transfer_20,
    }


async def handle_event(action: str, payload: Dict[str, Any]) -> Dict[str, Any]:
    """Route an OCPP action to its appropriate handler"""
    handlers = get_event_handlers()
    
    if action in handlers:
        try:
            return await handlers[action](payload)
        except Exception as e:
            logger.error(f"Error handling {action}: {e}")
            return {
                "status": "InternalError",
                "error": f"Failed to process {action}: {str(e)}"
            }
    else:
        return await handle_unknown_event(action, payload)


__all__ = [
    "handle_boot_notification",
    "handle_heartbeat", 
    "handle_start_transaction",
    "handle_stop_transaction",
    "handle_status_notification",
    "handle_meter_values",
    "handle_authorize",
    "handle_data_transfer",
    "handle_firmware_status_notification",
    "handle_diagnostic_status_notification",
    "handle_pause_transaction",
    "handle_resume_transaction",
    "handle_unknown_event",
    "get_event_handlers",
    "handle_event"
]
