"""Tier definitions and gating for Comply.

Local (CLI) usage: everything unlocked. No restrictions.
Managed (hosted) usage: tier enforcement applies.

Managed mode is activated by setting COMPLY_MANAGED=true (e.g. on Fly.io).
Without it, all check_* functions return True.
"""
from __future__ import annotations

import logging
import os
import yaml
from typing import Optional

log = logging.getLogger(__name__)

TIERS = {
    "free": {
        "label": "Free",
        "max_projects": 1,
        "frameworks": ["eu_ai_act"],
        "max_frameworks_per_scan": 1,
        "max_depth": "content",
        "exports": ["json"],
    },
    "pro": {
        "label": "Pro",
        "max_projects": 5,
        "frameworks": ["eu_ai_act", "nist_ai_rmf", "iso_42001"],
        "max_frameworks_per_scan": 3,
        "max_depth": "semantic",
        "exports": ["json", "docx", "zip", "sarif", "junit", "markdown"],
    },
    "enterprise": {
        "label": "Enterprise",
        "max_projects": -1,  # unlimited
        "frameworks": [],    # empty = all
        "max_frameworks_per_scan": -1,  # unlimited
        "max_depth": "semantic",
        "exports": ["json", "docx", "zip", "sarif", "junit", "markdown"],
    },
}

_CONFIG_DIR = os.path.expanduser("~/.comply")
_CONFIG_FILE = os.path.join(_CONFIG_DIR, "config.yaml")


def get_tier() -> str:
    """Return the current tier name (default: free).

    If a Pro/Enterprise tier is configured but the license key is invalid,
    falls back to free.
    """
    cfg = _load_config()
    tier = cfg.get("tier", "free")
    if tier in ("pro", "enterprise"):
        key = cfg.get("license_key", "")
        if not key:
            return "free"
        try:
            from comply.licensing import validate_license_key
            valid, _, _ = validate_license_key(key)
            if not valid:
                return "free"
        except Exception as e:
            log.debug("License validation failed, defaulting to free tier: %s", e)
    return tier


def get_tier_config() -> dict:
    """Return the full tier definition for the current tier."""
    tier = get_tier()
    return TIERS.get(tier, TIERS["free"])


def set_tier(tier: str, license_key: Optional[str] = None):
    """Set the tier. For Pro/Enterprise, a license key is required."""
    if tier not in TIERS:
        raise ValueError(f"Unknown tier: {tier}. Valid: {', '.join(TIERS.keys())}")
    if tier in ("pro", "enterprise") and not license_key:
        raise ValueError(f"{tier} tier requires a license key")
    cfg = _load_config()
    cfg["tier"] = tier
    if license_key:
        cfg["license_key"] = license_key
    _save_config(cfg)


def _is_managed() -> bool:
    """Return True only when running as a managed (hosted) service."""
    return os.environ.get("COMPLY_MANAGED", "").lower() in ("true", "1", "yes")


def check_framework_allowed(framework: str) -> bool:
    """Check if the given framework is allowed under the current tier."""
    if not _is_managed():
        return True
    tier_cfg = get_tier_config()
    allowed = tier_cfg["frameworks"]
    if not allowed:  # empty = all allowed
        return True
    return framework in allowed


def check_depth_allowed(depth: str) -> bool:
    """Check if the given scan depth is allowed under the current tier."""
    if not _is_managed():
        return True
    tier_cfg = get_tier_config()
    max_depth = tier_cfg["max_depth"]
    depth_order = ["structure", "content", "semantic"]
    return depth_order.index(depth) <= depth_order.index(max_depth)


def check_multi_framework_allowed(count: int) -> bool:
    """Check if scanning N frameworks at once is allowed under the current tier."""
    if not _is_managed():
        return True
    tier_cfg = get_tier_config()
    max_fw = tier_cfg.get("max_frameworks_per_scan", 1)
    if max_fw == -1:  # unlimited
        return True
    return count <= max_fw


def check_export_allowed(fmt: str) -> bool:
    """Check if the given export format is allowed under the current tier."""
    if not _is_managed():
        return True
    tier_cfg = get_tier_config()
    return fmt in tier_cfg["exports"]


def _load_config() -> dict:
    if not os.path.isfile(_CONFIG_FILE):
        return {"tier": "free"}
    try:
        with open(_CONFIG_FILE) as f:
            cfg = yaml.safe_load(f)
        return cfg if isinstance(cfg, dict) else {"tier": "free"}
    except (OSError, yaml.YAMLError) as e:
        log.debug("Failed to load comply config: %s", e)
        return {"tier": "free"}


def _save_config(cfg: dict):
    os.makedirs(_CONFIG_DIR, exist_ok=True)
    with open(_CONFIG_FILE, "w") as f:
        yaml.dump(cfg, f)
