"""
Kiwi tier gates.

Tiers: free < paid < premium
(Ultra not used in Kiwi — no human-in-the-loop operations.)

Uses circuitforge-core can_use() with Kiwi's feature map.
"""
from __future__ import annotations

from circuitforge_core.tiers.tiers import can_use as _can_use

# Features that unlock when the user supplies their own LLM backend.
KIWI_BYOK_UNLOCKABLE: frozenset[str] = frozenset({
    "recipe_suggestions",
    "expiry_llm_matching",
    "receipt_ocr",
    "recipe_scan",
    "style_classifier",
    "meal_plan_llm",
    "meal_plan_llm_timing",
    "community_fork_adapt",
})

# Sources subject to monthly cf-orch call caps. Subscription-based sources are uncapped.
LIFETIME_SOURCES: frozenset[str] = frozenset({"lifetime", "founders"})

# (source, tier) → monthly cf-orch call allowance
LIFETIME_ORCH_CAPS: dict[tuple[str, str], int] = {
    ("lifetime", "paid"):    60,
    ("lifetime", "premium"): 180,
    ("founders", "premium"): 300,
}

# Feature → minimum tier required
KIWI_FEATURES: dict[str, str] = {
    # Free tier
    "inventory_crud":        "free",
    "barcode_scan":          "free",
    "receipt_upload":        "free",
    "expiry_alerts":         "free",
    "export_csv":            "free",
    "leftover_mode":         "free",      # Rate-limited at API layer, not tier-gated
    "staple_library":        "free",

    # Paid tier
    "receipt_ocr":           "paid",   # BYOK-unlockable
    "visual_label_capture":  "paid",   # Camera capture for unenriched barcodes (kiwi#79)
    "recipe_suggestions":    "paid",   # BYOK-unlockable
    "expiry_llm_matching":   "paid",   # BYOK-unlockable
    "meal_planning":         "free",
    "meal_plan_config":      "paid",   # configurable meal types (breakfast/lunch/snack)
    "dietary_profiles":      "paid",
    "style_picker":          "paid",
    "recipe_collections":    "paid",
    "community_publish":     "paid",   # Publish plans/outcomes to community feed

    # Premium tier — heavy LLM features (model call per request)
    "meal_plan_llm":         "premium",  # LLM-assisted full-week plan generation; BYOK-unlockable
    "meal_plan_llm_timing":  "premium",  # LLM time fill-in for recipes missing corpus times; BYOK-unlockable
    "style_classifier":      "premium",  # LLM auto-tag for saved recipe style tags; BYOK-unlockable
    "community_fork_adapt":  "premium",  # Fork with LLM pantry adaptation; BYOK-unlockable
    "recipe_scan":           "premium",  # BYOK-unlockable: photo -> structured recipe
    "multi_household":       "premium",
    "background_monitoring": "premium",
}


def can_use(feature: str, tier: str, has_byok: bool = False) -> bool:
    """Return True if the given tier can access the feature.

    The 'local' tier is assigned to dev-bypass and non-cloud sessions —
    it has unrestricted access to all features.
    """
    if tier == "local":
        return True
    return _can_use(
        feature,
        tier,
        has_byok=has_byok,
        _features=KIWI_FEATURES,
        _byok_unlockable=KIWI_BYOK_UNLOCKABLE,
    )


def require_feature(feature: str, tier: str, has_byok: bool = False) -> None:
    """Raise ValueError if the tier cannot access the feature."""
    if not can_use(feature, tier, has_byok):
        from circuitforge_core.tiers.tiers import tier_label
        needed = tier_label(
            feature,
            has_byok=has_byok,
            _features=KIWI_FEATURES,
            _byok_unlockable=KIWI_BYOK_UNLOCKABLE,
        )
        raise ValueError(
            f"Feature '{feature}' requires {needed} tier. "
            f"Current tier: {tier}."
        )
