"""ISO 3166-1 alpha-2 country codes shared across zones, shipments, and APIs."""

from __future__ import annotations

# Gulf Cooperation Council members (KYC GCC ID country dropdown).
GCC_COUNTRY_CODES: tuple[str, ...] = ('AE', 'SA', 'OM', 'QA', 'BH', 'KW')

# GCC and primary operating countries listed first in admin UIs.
_PRIORITY_CODES = ('AE', 'SA', 'OM', 'QA', 'BH', 'KW', 'PK', 'IN', 'EG', 'JO', 'LB', 'IQ', 'YE')

COUNTRY_BY_CODE: dict[str, str] = {
    'AE': 'United Arab Emirates',
    'SA': 'Saudi Arabia',
    'OM': 'Oman',
    'QA': 'Qatar',
    'BH': 'Bahrain',
    'KW': 'Kuwait',
    'PK': 'Pakistan',
    'IN': 'India',
    'EG': 'Egypt',
    'JO': 'Jordan',
    'LB': 'Lebanon',
    'IQ': 'Iraq',
    'YE': 'Yemen',
    'AF': 'Afghanistan',
    'AL': 'Albania',
    'DZ': 'Algeria',
    'AD': 'Andorra',
    'AO': 'Angola',
    'AR': 'Argentina',
    'AM': 'Armenia',
    'AU': 'Australia',
    'AT': 'Austria',
    'AZ': 'Azerbaijan',
    'BD': 'Bangladesh',
    'BY': 'Belarus',
    'BE': 'Belgium',
    'BJ': 'Benin',
    'BO': 'Bolivia',
    'BA': 'Bosnia and Herzegovina',
    'BR': 'Brazil',
    'BN': 'Brunei',
    'BG': 'Bulgaria',
    'BF': 'Burkina Faso',
    'KH': 'Cambodia',
    'CM': 'Cameroon',
    'CA': 'Canada',
    'CL': 'Chile',
    'CN': 'China',
    'CO': 'Colombia',
    'CR': 'Costa Rica',
    'HR': 'Croatia',
    'CY': 'Cyprus',
    'CZ': 'Czechia',
    'DK': 'Denmark',
    'DJ': 'Djibouti',
    'EC': 'Ecuador',
    'EE': 'Estonia',
    'ET': 'Ethiopia',
    'FI': 'Finland',
    'FR': 'France',
    'GE': 'Georgia',
    'DE': 'Germany',
    'GH': 'Ghana',
    'GR': 'Greece',
    'GT': 'Guatemala',
    'HK': 'Hong Kong',
    'HU': 'Hungary',
    'IS': 'Iceland',
    'ID': 'Indonesia',
    'IR': 'Iran',
    'IE': 'Ireland',
    'IL': 'Israel',
    'IT': 'Italy',
    'JP': 'Japan',
    'KZ': 'Kazakhstan',
    'KE': 'Kenya',
    'KR': 'Korea, Republic of',
    'XK': 'Kosovo',
    'KG': 'Kyrgyzstan',
    'LV': 'Latvia',
    'LY': 'Libya',
    'LT': 'Lithuania',
    'LU': 'Luxembourg',
    'MY': 'Malaysia',
    'MV': 'Maldives',
    'ML': 'Mali',
    'MT': 'Malta',
    'MX': 'Mexico',
    'MD': 'Moldova',
    'MA': 'Morocco',
    'MM': 'Myanmar',
    'NP': 'Nepal',
    'NL': 'Netherlands',
    'NZ': 'New Zealand',
    'NE': 'Niger',
    'NG': 'Nigeria',
    'NO': 'Norway',
    'PS': 'Palestine',
    'PE': 'Peru',
    'PH': 'Philippines',
    'PL': 'Poland',
    'PT': 'Portugal',
    'RO': 'Romania',
    'RU': 'Russia',
    'RW': 'Rwanda',
    'SN': 'Senegal',
    'RS': 'Serbia',
    'SG': 'Singapore',
    'SK': 'Slovakia',
    'SI': 'Slovenia',
    'SO': 'Somalia',
    'ZA': 'South Africa',
    'ES': 'Spain',
    'LK': 'Sri Lanka',
    'SD': 'Sudan',
    'SE': 'Sweden',
    'CH': 'Switzerland',
    'SY': 'Syria',
    'TW': 'Taiwan',
    'TJ': 'Tajikistan',
    'TZ': 'Tanzania',
    'TH': 'Thailand',
    'TN': 'Tunisia',
    'TR': 'Turkey',
    'TM': 'Turkmenistan',
    'UG': 'Uganda',
    'UA': 'Ukraine',
    'GB': 'United Kingdom',
    'US': 'United States',
    'UZ': 'Uzbekistan',
    'VE': 'Venezuela',
    'VN': 'Vietnam',
    'ZM': 'Zambia',
    'ZW': 'Zimbabwe',
}

COUNTRY_NAME_ALIASES: dict[str, str] = {
    'uae': 'AE',
    'u.a.e.': 'AE',
    'united arab emirates': 'AE',
    'emirates': 'AE',
    'ksa': 'SA',
    'saudi arabia': 'SA',
    'kingdom of saudi arabia': 'SA',
    'pakistan': 'PK',
    'oman': 'OM',
    'qatar': 'QA',
    'bahrain': 'BH',
    'kuwait': 'KW',
    'india': 'IN',
    'egypt': 'EG',
}


def _sorted_country_choices() -> list[tuple[str, str]]:
    priority = [(code, COUNTRY_BY_CODE[code]) for code in _PRIORITY_CODES if code in COUNTRY_BY_CODE]
    rest = sorted(
        ((code, name) for code, name in COUNTRY_BY_CODE.items() if code not in _PRIORITY_CODES),
        key=lambda item: item[1],
    )
    return priority + rest


COUNTRY_CHOICES: list[tuple[str, str]] = _sorted_country_choices()

GCC_COUNTRY_CHOICES: list[tuple[str, str]] = [
    (code, COUNTRY_BY_CODE[code]) for code in GCC_COUNTRY_CODES if code in COUNTRY_BY_CODE
]


def is_gcc_country_code(value: str | None) -> bool:
    code = normalize_country_code(value)
    return bool(code and code in GCC_COUNTRY_CODES)


def normalize_country_code(value: str | None) -> str | None:
    if value is None:
        return None
    code = str(value).strip().upper()
    if not code:
        return None
    if len(code) == 2 and code in COUNTRY_BY_CODE:
        return code
    return None


def is_valid_country_code(value: str | None) -> bool:
    return normalize_country_code(value) is not None


def country_name_for_code(value: str | None) -> str:
    code = normalize_country_code(value)
    if not code:
        return ''
    return COUNTRY_BY_CODE.get(code, code)


def country_name_to_code(value: str | None) -> str | None:
    if not value:
        return None
    direct = normalize_country_code(value)
    if direct:
        return direct
    normalized = str(value).strip().lower()
    if normalized in COUNTRY_NAME_ALIASES:
        return COUNTRY_NAME_ALIASES[normalized]
    for code, name in COUNTRY_BY_CODE.items():
        if name.lower() == normalized:
            return code
    return None


def return_trips_allowed_for_country(country_code: str | None) -> bool:
    from core.models import Zone

    code = normalize_country_code(country_code)
    if not code:
        return False
    return Zone.objects.filter(country_code=code, allow_return_trips=True).exists()


def is_operational_country(country_code: str | None) -> bool:
    from core.models import Zone

    code = normalize_country_code(country_code)
    if not code:
        return False
    return Zone.objects.filter(country_code=code).exists()


DEFAULT_ZONE_SEARCH_RADIUS_KM = 25


def zone_search_radius_km(country_code: str | None) -> tuple[float, str]:
    """Return search radius in km and source ('zone' or 'default') for a country code."""
    from core.models import Zone

    code = normalize_country_code(country_code)
    if code:
        zone = Zone.objects.filter(country_code=code).first()
        if zone and zone.radius_km is not None:
            return float(zone.radius_km), 'zone'
    return float(DEFAULT_ZONE_SEARCH_RADIUS_KM), 'default'


def transporter_load_search_radius_km(country_code: str | None) -> tuple[float, str]:
    """Zone radius for transporter load APIs, else platform default load_visibility_radius_km."""
    from accounts.models import PlatformSettings
    from core.models import Zone

    code = normalize_country_code(country_code)
    if code:
        zone = Zone.objects.filter(country_code=code).first()
        if zone and zone.radius_km is not None:
            return float(zone.radius_km), 'zone'
    platform = PlatformSettings.load()
    return float(platform.load_visibility_radius_km), 'default'


def operational_region_error_for_country(country_code: str | None) -> str | None:
    """Return a user-facing error when the country is not configured as a zone."""
    code = normalize_country_code(country_code)
    if not code:
        return None
    if is_operational_country(code):
        return None
    name = country_name_for_code(code) or code
    return f'We are not operating in {name}.'


def return_trip_error_for_pickup_country(country_code: str | None) -> str | None:
    """Return a user-facing error when return trips are not allowed from the pickup country."""
    code = normalize_country_code(country_code)
    if not code:
        return 'Pickup country is required for return trips.'
    if return_trips_allowed_for_country(code):
        return None
    name = country_name_for_code(code) or code
    return f'Return trips are not allowed from {name}.'


OPERATIONAL_REGION_ERROR_PREFIX = 'We are not operating in '
RETURN_TRIP_ERROR_PREFIX = 'Return trips are not allowed from '
RETURN_TRIP_PICKUP_REQUIRED = 'Pickup country is required for return trips.'


def extract_flat_shipment_validation_error(detail) -> str | None:
    """Return a flat shipment validation message (zone country, return trip, etc.)."""
    if isinstance(detail, str):
        if detail.startswith(OPERATIONAL_REGION_ERROR_PREFIX):
            return detail
        if detail.startswith(RETURN_TRIP_ERROR_PREFIX) or detail == RETURN_TRIP_PICKUP_REQUIRED:
            return detail
        return None
    if isinstance(detail, list) and detail:
        return extract_flat_shipment_validation_error(detail[0])
    if not isinstance(detail, dict):
        return None
    for field in ('pickup_country_code', 'delivery_country_code', 'is_return', 'non_field_errors'):
        if field in detail:
            found = extract_flat_shipment_validation_error(detail[field])
            if found:
                return found
    return None


def extract_operational_region_error(detail) -> str | None:
    """Return a flat zone-country message from DRF ValidationError detail."""
    message = extract_flat_shipment_validation_error(detail)
    if message and message.startswith(OPERATIONAL_REGION_ERROR_PREFIX):
        return message
    return None
