"""Map raw delivery-method strings to canonical carrier names.

Carriers: DPD · DHL · Paket24 · Pickup
Special token FREE_SHIPPING resolves to DPD for EU, DHL for non-EU.
Rules are checked in order; first keyword (substring, case-insensitive) wins.
"""
import json

EU_COUNTRIES = {
    'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR',
    'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL',
    'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE',
}

CARRIER_FREE = 'FREE_SHIPPING'   # sentinel resolved by country at call time

DEFAULT_RULES = [
    {'match': 'dhl',                      'carrier': 'DHL'},
    {'match': 'paket24',                  'carrier': 'Paket24'},
    {'match': 'dpd',                      'carrier': 'DPD'},
    {'match': 'gls',                      'carrier': 'GLS'},
    {'match': 'besplatna dostava',        'carrier': 'DPD'},
    {'match': 'kostenloser versand',      'carrier': 'DPD'},
    {'match': 'free shipping',            'carrier': CARRIER_FREE},
    {'match': 'osobno preuzimanje',       'carrier': 'Pickup'},
    {'match': 'soldered electronics hq',  'carrier': 'Pickup'},
    {'match': 'pickup',                   'carrier': 'Pickup'},
]

# Maps display carrier names → internal keys used by _process_single_order
_INTERNAL = {
    'DHL':     'dhl_eu',
    'DPD':     'dpd',
    'Paket24': 'paket24',
    'GLS':     'gls',
    'Pickup':  'pickup',
}


def get_carrier(delivery_method: str, country: str = '', rules: list = None) -> str:
    """Return the canonical carrier display name (e.g. 'DPD', 'DHL', 'Paket24', 'Pickup').

    FREE_SHIPPING resolves to DPD for EU countries, DHL for others.
    Returns 'Other' if no rule matches.
    """
    if rules is None:
        rules = DEFAULT_RULES
    m  = (delivery_method or '').strip().lower()
    cc = (country or '').strip().upper()

    for rule in rules:
        keyword = (rule.get('match') or '').strip().lower()
        if keyword and keyword in m:
            carrier = rule.get('carrier', '')
            if carrier == CARRIER_FREE:
                return 'DPD' if cc in EU_COUNTRIES else 'DHL'
            return carrier

    return 'Other'


def get_internal_carrier(delivery_method: str, country: str = '', rules: list = None) -> str:
    """Like get_carrier() but returns the internal key used by the order processor."""
    display = get_carrier(delivery_method, country, rules)
    return _INTERNAL.get(display, 'other')


def rules_from_json(json_str: str) -> list:
    """Parse rules from a JSON string; return DEFAULT_RULES on error."""
    if not json_str:
        return DEFAULT_RULES
    try:
        rules = json.loads(json_str)
        if isinstance(rules, list):
            return rules
    except Exception:
        pass
    return DEFAULT_RULES
