#!/usr/bin/env python3
"""
🔗 Connecteur applicatif - Web Sentinel

Ce module fournit une couche d'accès aux informations de licence et aux
fonctionnalités runtime de l'application réelle Web Sentinel. Il est utilisé
par le panneau d'administration (`admin_panel.py`) pour :

* Consulter l'état de la licence embarquée (tier, expiration, fonctionnalités)
* Installer/importer un nouveau fichier de licence
* Exécuter des tests de permissions afin de valider les comportements attendus
* Exposer le chemin du fichier licence et l'emplacement des artefacts runtime
"""

from __future__ import annotations

import sys
from pathlib import Path
from typing import Dict, List

# Rendre le package principal disponible lors de l'exécution directe du module.
sys.path.insert(0, str(Path(__file__).parent.parent))

from web_sentinel.license.license_manager import LicenceError
from web_sentinel.license.runtime_bridge import (
    get_license_bridge,
    initialize_license_system,
)


class RealAppConnector:
    """Pont entre le panneau d'administration et l'application Web Sentinel."""

    def __init__(self) -> None:
        self._bridge = get_license_bridge()
        # L'admin panel n'a pas besoin de licence pour démarrer
        # Il peut générer et gérer les licences même sans licence active
        self.initialized: bool = False
        self.connection_error: str | None = "Admin Panel - Aucune licence requise pour démarrer"
        print("🎛️ Admin Panel démarré - Prêt pour gestion des licences")

    # --------------------------------------------------------------------- #
    # Accès licence
    # --------------------------------------------------------------------- #

    def refresh(self) -> bool:
        """Rafraîchir l'état de la licence depuis le runtime."""
        try:
            # Initialiser le système de licence si pas encore fait
            if not self.initialized:
                initialize_license_system()
            
            refreshed = self._bridge.refresh()
        except LicenceError as exc:
            self.initialized = False
            self.connection_error = str(exc)
            return False
        except Exception as exc:
            self.initialized = False
            self.connection_error = f"Erreur système licence : {exc}"
            return False
        else:
            self.initialized = True
            self.connection_error = None
            return refreshed

    def get_license_status(self) -> Dict:
        """Retourner l'état courant de la licence (toujours un dictionnaire)."""
        status = self._bridge.get_license_status()
        # Normaliser la structure attendue par l'interface
        status.setdefault("features_enabled", {})
        status.setdefault("tier", "FREE")
        status.setdefault("status", "FREE_MODE")
        status.setdefault("valid", False)
        status.setdefault("license_id", None)
        status.setdefault("expires_in_days", None)
        status.setdefault("alert_level", None)
        status.setdefault("alert_threshold", None)
        status.setdefault("max_domains", None)
        status.setdefault("max_users", None)
        status.setdefault("grace_hours", 0)
        return status

    def install_license(self, licence_path: Path) -> bool:
        """
        Installer un nouveau fichier de licence puis rafraîchir le runtime.

        Args:
            licence_path: chemin du fichier .lic sélectionné par l'administrateur.
        """
        if not licence_path.exists():
            raise LicenceError(f"Licence introuvable: {licence_path}")
        try:
            self._bridge.install_new_license(licence_path)
            self.refresh()
        except LicenceError as exc:
            self.connection_error = str(exc)
            self.initialized = False
            raise
        return True

    def get_license_file_path(self) -> Path:
        """Chemin du fichier licence utilisé par l'application."""
        return getattr(self._bridge, "licence_path", Path.home() / ".web-sentinel" / "license.lic")

    # --------------------------------------------------------------------- #
    # Tests de permissions
    # --------------------------------------------------------------------- #

    def run_permission_tests(self) -> Dict[str, List[Dict]]:
        """
        Exécuter une série de tests de permissions basés sur la licence.

        Returns:
            Un dictionnaire contenant les résultats détaillés des tests.
        """
        validator = self._bridge.get_runtime_validator()
        manager = self._bridge.get_runtime_manager()

        def _evaluate(check_callable, fallback_value: bool) -> Dict:
            try:
                check_callable()
            except Exception as exc:  # noqa: BLE001 – remonter l'erreur dans le résultat
                return {"allowed": False, "details": str(exc)}
            return {"allowed": True, "details": None if fallback_value else "Accessible via validation explicite."}

        tests = [
            ("invasive_tests", validator.ensure_invasive_tests_allowed, manager.can_use_invasive_tests()),
            ("html_export", validator.ensure_html_export_allowed, manager.can_export_html()),
            ("api_access", validator.ensure_api_allowed, manager.can_use_api()),
        ]

        results = []
        for feature, ensure_call, fallback in tests:
            outcome = _evaluate(ensure_call, fallback)
            outcome["feature"] = feature
            outcome["runtime_flag"] = fallback
            results.append(outcome)

        capabilities = {
            "tier": manager.tier.value if hasattr(manager.tier, "value") else str(manager.tier),
            "domain_limit": manager.get_domain_limit(),
            "user_limit": getattr(manager, "get_user_limit", lambda: None)(),
            "can_use_invasive_tests": manager.can_use_invasive_tests(),
            "can_export_html": manager.can_export_html(),
            "can_use_api": manager.can_use_api(),
        }

        return {
            "tests": results,
            "capabilities": capabilities,
        }


__all__ = ["RealAppConnector"]
