"""Mappings from source vocabularies to the canonical AFP vocabulary.

Drupal 7 / Backdrop `advisory` nodes (Sierra archive, Gulmarg, Chile, the
avalanche-center template) share one field schema:
  field_type_N        1 Storm Slab, 2 Deep Slab, 3 Wind Slab, 4 Wet Slab,
                      5 Persistent Slab, 6 Loose Wet, 7 Loose Dry,
                      8 Normal Caution, 9 Cornice, 10 Glide
  field_likelihood_N  1 Unlikely .. 5 Certain
  field_size_N        1..5 (D1..D5), up to two values = a range
  field_rose_N        danger_rose: columns _0.._23 (0-7 upper, 8-15 middle,
                      16-23 lower; N clockwise); any nonzero = selected
  field_danger_rating_1/2/3   '0'..'5' for lower / middle / upper
"""

from __future__ import annotations

import re

from .engine import cell_to_location

# Drupal field_type key -> AFP avalanche_problem_id. Key 8 ("Normal Caution")
# has no problem type under current guidance: it sets forecasts.normal_caution.
DRUPAL_PROBLEM_TO_AFP = {1: 2, 2: 5, 3: 3, 4: 7, 5: 4, 6: 6, 7: 1, 9: 8, 10: 9}
AFP_TO_DRUPAL_PROBLEM = {v: k for k, v in DRUPAL_PROBLEM_TO_AFP.items()}
DRUPAL_NORMAL_CAUTION = 8

AFP_PROBLEM_NAMES = {
    1: "Dry Loose",
    2: "Storm Slab",
    3: "Wind Slab",
    4: "Persistent Slab",
    5: "Deep Persistent Slab",
    6: "Wet Loose",
    7: "Wet Slab",
    8: "Cornice",
    9: "Glide",
}

LIKELIHOOD_WORDS = {
    "unlikely": 1,
    "possible": 2,
    "likely": 3,
    "very likely": 4,
    "almost certain": 5,
    "certain": 5,
}
LIKELIHOOD_NAMES = {1: "unlikely", 2: "possible", 3: "likely", 4: "very likely", 5: "certain"}


def drupal_problem_type(value) -> tuple[int | None, bool]:
    """Return (afp_problem_id, is_normal_caution) for a Drupal field_type value."""
    try:
        key = int(value)
    except (TypeError, ValueError):
        return None, False
    if key == DRUPAL_NORMAL_CAUTION:
        return None, True
    return DRUPAL_PROBLEM_TO_AFP.get(key), False


def rose_cells_to_locations(values: dict[int, int | None]) -> list[str]:
    """danger_rose column values {cell_index: value} -> selected AFP locations."""
    out = []
    for cell in range(24):
        v = values.get(cell)
        if v not in (None, 0, "0", ""):
            loc = cell_to_location(cell)
            if loc:
                out.append(loc)
    return out


def parse_likelihood(value) -> int | None:
    if value is None or value == "":
        return None
    if isinstance(value, int | float) or str(value).strip().isdigit():
        v = int(value)
        return v if 1 <= v <= 5 else None
    return LIKELIHOOD_WORDS.get(str(value).strip().lower())


def parse_sizes(values) -> tuple[float | None, float | None]:
    """A list of size values (Drupal ints or AFP strings like "1.5") -> (min, max) D-scale."""
    nums = []
    for v in values or []:
        try:
            f = float(v)
        except (TypeError, ValueError):
            continue
        if 1 <= f <= 5:
            nums.append(f)
    if not nums:
        return None, None
    return min(nums), max(nums)


def parse_danger(value) -> int | None:
    try:
        v = int(value)
    except (TypeError, ValueError):
        return None
    return v if 0 <= v <= 5 else None


TITLE_DATE = re.compile(r"(\d{4})-(\d{2})-(\d{2})")


def date_from_title(title: str | None) -> str | None:
    m = TITLE_DATE.search(title or "")
    return f"{m.group(1)}-{m.group(2)}-{m.group(3)}" if m else None


def season_for(date_iso: str) -> str:
    """Northern-hemisphere winter season label, e.g. 2020-12-01 -> '2020-21'."""
    y, m = int(date_iso[:4]), int(date_iso[5:7])
    start = y if m >= 8 else y - 1
    return f"{start}-{str(start + 1)[-2:]}"
