"""
Utility functions for the crawler framework.

Date formatting, selector utilities, and other helper functions.
"""

import logging
from datetime import datetime
from typing import Any

from .exceptions import InvalidInstructionError


def setup_logger(name: str) -> logging.Logger:
    """Create a structured logger for the crawler framework."""
    logger = logging.getLogger(name)
    if not logger.handlers:
        handler = logging.StreamHandler()
        formatter = logging.Formatter(
            "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
            datefmt="%Y-%m-%d %H:%M:%S",
        )
        handler.setFormatter(formatter)
        logger.addHandler(handler)
        logger.setLevel(logging.INFO)
    return logger


def format_date(value: str, target_format: str) -> str:
    """
    Convert a date string to the target format.

    Input format is expected to be ISO 8601 (YYYY-MM-DD).
    Target format uses strftime directives mapped from common patterns.

    Args:
        value: Date string in ISO 8601 format (YYYY-MM-DD)
        target_format: Target format pattern (e.g., "DD.MM.YYYY", "MM/DD/YYYY")

    Returns:
        Formatted date string

    """
    # Using naive datetime intentionally - we're only converting date formats, not handling timezones
    input_date = datetime.strptime(value, "%Y-%m-%d")  # noqa: DTZ007

    format_mapping: dict[str, str] = {
        "DD.MM.YYYY": "%d.%m.%Y",
        "MM/DD/YYYY": "%m/%d/%Y",
        "YYYY-MM-DD": "%Y-%m-%d",
        "DD/MM/YYYY": "%d/%m/%Y",
        "YYYY/MM/DD": "%Y/%m/%d",
        "DD-MM-YYYY": "%d-%m-%Y",
        "MM-DD-YYYY": "%m-%d-%Y",
    }

    strftime_format = format_mapping.get(target_format)
    if strftime_format is None:
        msg = f"Unsupported date format: {target_format}"
        raise InvalidInstructionError(msg)

    return input_date.strftime(strftime_format)


def get_value_for_field(input_data: dict[str, Any], data_key: str) -> Any:
    """
    Retrieve a value from input_data by key.

    Does not provide defaults - missing keys will be handled by the caller
    through MissingDataError.

    Args:
        input_data: Dictionary of field values
        data_key: Key to retrieve

    Returns:
        The value if found, or None if key does not exist

    """
    return input_data.get(data_key)


def normalize_selector(selector: str) -> str:
    """
    Normalize a CSS selector for consistent usage.

    Strips whitespace and validates basic selector syntax.

    Args:
        selector: CSS selector string

    Returns:
        Normalized selector string

    """
    normalized = selector.strip()
    if not normalized:
        msg = "Empty selector provided"
        raise InvalidInstructionError(msg)
    return normalized
