"""Tier configuration helpers (domain limits, SAST quotas, feature flags)."""

from __future__ import annotations

from copy import deepcopy
from typing import Any, Dict, Optional

from sqlalchemy.orm import Session

from .models import AdminConfig

TIER_CONFIG_KEY = "tier_profiles"

DEFAULT_TIER_PROFILES: Dict[str, Dict[str, Any]] = {
    "FREE": {
        "label": "Free",
        "max_domains": 5,  # Scan DNS limité (5 domaines pour tester)
        "max_users": 0,  # Pas de compte créé (usage anonyme/sans auth)
        "allow_source_scan": False,
        "max_source_files": 0,
        "max_source_size_mb": 0,
        "advanced_rules": False,
        "allow_invasive_tests": False,
        "allow_html_export": False,
        "allow_multi_user": False,
        "allow_api_access": False,
    },
    "STARTER": {
        "label": "Starter",
        "max_domains": -1,  # DNS illimité
        "max_users": 1,  # Compte créé
        "allow_source_scan": True,  # SAST activé pour motivation
        "max_source_files": 10,  # 10 fichiers/mois (limitation à implémenter)
        "max_source_size_mb": 10,  # 10 MB max (était 5)
        "advanced_rules": False,
        "allow_invasive_tests": False,
        "allow_html_export": True,  # Export HTML pour partager résultats
        "allow_multi_user": False,
        "allow_api_access": False,
    },
    "PRO": {
        "label": "Pro",
        "max_domains": -1,  # DNS illimité
        "max_users": 1,  # 1 utilisateur seulement (pas de collègues)
        "allow_source_scan": True,
        "max_source_files": 100,  # 100 fichiers/mois
        "max_source_size_mb": 50,  # 50 MB max
        "advanced_rules": False,
        "allow_invasive_tests": True,
        "allow_html_export": True,
        "allow_multi_user": False,  # Pas de multi-user
        "allow_api_access": True,  # API pour intégration CI/CD
    },
    "ENTERPRISE": {
        "label": "Enterprise",
        "max_domains": -1,  # DNS illimité
        "max_users": 10,  # 10 comptes max (création collègues)
        "allow_source_scan": True,
        "max_source_files": 500,  # 500 fichiers/mois
        "max_source_size_mb": 200,  # 200 MB max
        "advanced_rules": True,
        "allow_invasive_tests": True,
        "allow_html_export": True,
        "allow_multi_user": True,  # Multi-user activé
        "allow_api_access": True,
    },
    "SYSOP": {
        "label": "SysOp",
        "max_domains": -1,
        "max_users": -1,
        "allow_source_scan": True,
        "max_source_files": -1,
        "max_source_size_mb": -1,
        "advanced_rules": True,
        "allow_invasive_tests": True,
        "allow_html_export": True,
        "allow_multi_user": True,
        "allow_api_access": True,
    },
}


def _normalize_key(tier: str) -> str:
    return (tier or "FREE").strip().upper() or "FREE"


def _merge_profiles(custom: Optional[Dict[str, Dict[str, Any]]]) -> Dict[str, Dict[str, Any]]:
    merged: Dict[str, Dict[str, Any]] = {key: deepcopy(value) for key, value in DEFAULT_TIER_PROFILES.items()}
    if not custom:
        return merged

    for raw_key, payload in custom.items():
        key = _normalize_key(raw_key)
        defaults = merged.get(key, deepcopy(DEFAULT_TIER_PROFILES["FREE"]))
        merged[key] = {**defaults, **payload}

    # Preserve labels for any newly introduced tiers
    for key, profile in merged.items():
        profile.setdefault("label", key.title())
    return merged


def load_tier_profiles(session: Optional[Session] = None) -> Dict[str, Dict[str, Any]]:
    """Load tier profiles merged with defaults."""
    if session is None:
        return _merge_profiles({})

    config = (
        session.query(AdminConfig)
        .filter(AdminConfig.key == TIER_CONFIG_KEY)
        .first()
    )
    raw_value = config.value if config and isinstance(config.value, dict) else {}
    return _merge_profiles(raw_value)


def get_tier_profile(session: Optional[Session], tier: str) -> Dict[str, Any]:
    profiles = load_tier_profiles(session)
    key = _normalize_key(tier)
    return profiles.get(key) or profiles["FREE"]


def resolve_license_limits(
    session: Optional[Session],
    tier: str,
    max_domains: Optional[int] = None,
    max_users: Optional[int] = None,
) -> Dict[str, int]:
    profile = get_tier_profile(session, tier)
    return {
        "max_domains": profile["max_domains"] if max_domains is None else max_domains,
        "max_users": profile["max_users"] if max_users is None else max_users,
    }


def resolve_feature_flags(session: Optional[Session], tier: str) -> Dict[str, bool]:
    profile = get_tier_profile(session, tier)
    return {
        "allow_invasive_tests": bool(profile.get("allow_invasive_tests", False)),
        "allow_html_export": bool(profile.get("allow_html_export", False)),
        "allow_multi_user": bool(profile.get("allow_multi_user", False)),
        "allow_api_access": bool(profile.get("allow_api_access", False)),
    }


def resolve_sast_settings(
    session: Optional[Session],
    tier: str,
    *,
    allow_source_scan: Optional[bool] = None,
    max_source_files: Optional[int] = None,
    max_source_size_mb: Optional[int] = None,
    advanced_rules: Optional[bool] = None,
) -> Dict[str, int | bool]:
    """Return sanitized SAST settings using tier profiles when values are None."""
    profile = get_tier_profile(session, tier)
    return {
        "allow_source_scan": profile["allow_source_scan"] if allow_source_scan is None else allow_source_scan,
        "max_source_files": profile["max_source_files"] if max_source_files is None else max_source_files,
        "max_source_size_mb": profile["max_source_size_mb"] if max_source_size_mb is None else max_source_size_mb,
        "advanced_rules": profile["advanced_rules"] if advanced_rules is None else advanced_rules,
    }
