"""Printer supply classification and part-number lookup.

Part numbers now live in the modelsupplies table (see seed_supplies.py),
managed through the API/UI. This module keeps the runtime logic that is not
per-model data: classifying a reported level into ok/low/critical (waste
cartridges invert), deriving supply type and color from a Zabbix item name,
and reading the matching part numbers out of the database.
"""

from typing import Dict, List, Optional


# display thresholds (percent remaining) for the ok/low/critical report badge
CRITICAL_THRESHOLD = 5
LOW_THRESHOLD = 10

# toner email-alert tiers (percent remaining). Distinct from the display
# badge above: a warning email fires at or below TONER_WARNING_THRESHOLD, a
# critical email at or below TONER_CRITICAL_THRESHOLD (empty).
TONER_WARNING_THRESHOLD = 5
TONER_CRITICAL_THRESHOLD = 0


def alerttier(remaining: float, warning: float = TONER_WARNING_THRESHOLD,
              critical: float = TONER_CRITICAL_THRESHOLD) -> str:
    """Map a toner percent-remaining to an email-alert tier.

    critical at or below the critical threshold (default 0 = empty), warning at
    or below the warning threshold (default 5), else ok. Both are configurable
    (printers_alert_critical_threshold / printers_alert_warning_threshold)."""
    if remaining <= critical:
        return 'critical'
    if remaining <= warning:
        return 'warning'
    return 'ok'


# tier severity rank; an alert fires only when the rank increases (worsens)
TIER_RANK = {'ok': 0, 'warning': 1, 'critical': 2}


def derivesupplytype(name: str) -> str:
    """Map a Zabbix item name to a supply type."""
    lowername = (name or "").lower()
    if "waste" in lowername:
        return "waste"
    if "drum" in lowername or "imaging" in lowername:
        return "drum"
    if "maintenance" in lowername or "fuser" in lowername:
        return "maintenance"
    return "toner"


def derivecolor(name: str, tagcolor: Optional[str] = None) -> str:
    """Best-effort supply color from a Zabbix color tag, then the item name."""
    color = (tagcolor or "").lower()
    if "black" in color:
        return "black"
    if color in ("cyan", "magenta", "yellow"):
        return color
    if color in ("grey", "gray"):
        return "gray"

    lowername = (name or "").lower()
    for candidate in ("cyan", "magenta", "yellow", "black"):
        if candidate in lowername:
            return candidate
    return "none"


def classifysupply(level: float, name: str, vendor: Optional[str]) -> Dict:
    """Classify one supply item into ok/low/critical.

    Waste cartridge fill is inverted vs a toner level: a full waste cartridge
    is bad. Standard vendors report waste as percent FULL (high = bad). Xerox
    EC/AltaLink series report waste as percent capacity REMAINING (low = bad),
    same direction as toner. Normalise everything to percent remaining first.
    """
    lowername = (name or "").lower()
    iswaste = "waste" in lowername
    isdrum = "drum" in lowername or "imaging" in lowername
    isxerox = bool(vendor) and "xerox" in vendor.lower()

    if iswaste and not isxerox:
        remaining = 100 - level
    else:
        remaining = level

    if remaining <= CRITICAL_THRESHOLD:
        status = "critical"
    elif remaining <= LOW_THRESHOLD:
        status = "low"
    else:
        status = "ok"

    return {
        "status": status,
        "remaining": round(remaining, 1),
        "iswaste": iswaste,
        "isdrum": isdrum,
    }


def lookupsupplies(modelnumberid: Optional[int], color: str,
                   supplytype: str) -> List[Dict]:
    """Part-number options for a model + color + supply type, from the DB.

    Returns every matching capacity tier (standard / high / metered / ...) so
    the report can show all reorder options, like the classic report did.
    """
    if not modelnumberid:
        return []

    from ..models import ModelSupply

    query = ModelSupply.query.filter_by(
        modelnumberid=modelnumberid,
        supplytype=supplytype,
        isactive=True,
    )
    # toners are color-specific; drum/waste/maintenance are not
    if supplytype == 'toner' and color and color != 'none':
        query = query.filter_by(color=color)

    rows = query.order_by(ModelSupply.capacitytier).all()
    return [{
        'partnumber': row.partnumber,
        'marketingname': row.marketingname,
        'capacitytier': row.capacitytier,
        'pageyield': row.pageyield,
    } for row in rows]
