"""
InsAIts SDK - Readiness Checker
================================
System self-validation that checks whether all subsystems are
properly configured before the monitor processes messages.

Checks:
    1. License: API key validation status and tier
    2. Local embeddings: sentence-transformers model availability
    3. Ollama: Local LLM reachability (optional)
    4. Cloud: API backend reachability
    5. Anomaly engine: Detector initialization state
    6. Storage: Disk write access for caches and audit logs

Each check returns a structured result with status, detail, and
whether it is critical (blocks operation) or advisory (warning only).
"""

import logging
import os  # noqa: F401
import tempfile  # noqa: F401
import time
from pathlib import Path
from typing import Any, Dict, List, Optional  # noqa: F401

logger = logging.getLogger(__name__)


# Checks that MUST pass for the system to be considered ready
CRITICAL_CHECKS = frozenset({
    "license",
    "embeddings_local",
    "anomaly_engine",
    "storage",
})


def _make_check(
    status: str, detail: str, critical: bool = False
) -> Dict[str, Any]:
    """Create a standardized check result dict."""
    return {
        "status": status,
        "detail": detail,
        "critical": critical,
    }


class ReadinessChecker:
    """Validates that all InsAIts subsystems are operational.

    Usage:
        checker = ReadinessChecker(monitor_instance)
        result = checker.check()

        if result["ready"]:
            # All critical checks passed
            ...
        else:
            for name, check in result["checks"].items():
                if check["status"] == "fail":
                    logger.error(f"{name}: {check['detail']}")
    """

    def __init__(self, monitor: Any):
        """Initialize with a reference to the insAItsMonitor instance.

        Args:
            monitor: The insAItsMonitor instance to validate
        """
        self._monitor = monitor

    def check(self) -> Dict[str, Any]:
        """Run all readiness checks and return aggregated result.

        Returns:
            Dict with:
                ready (bool): True if all critical checks pass
                checks (Dict): Individual check results keyed by name
                warnings (List[str]): Non-critical issues
                errors (List[str]): Critical failures
                timestamp (float): When the check was performed
        """
        checks = {
            "license": self._check_license(),
            "embeddings_local": self._check_local_embeddings(),
            "ollama": self._check_ollama(),
            "cloud": self._check_cloud(),
            "anomaly_engine": self._check_anomaly_engine(),
            "storage": self._check_storage(),
        }

        warnings: List[str] = []
        errors: List[str] = []

        for name, result in checks.items():
            if result["status"] == "fail" and result.get("critical", False):
                errors.append(f"{name}: {result['detail']}")
            elif result["status"] == "warn":
                warnings.append(f"{name}: {result['detail']}")
            elif result["status"] == "fail":
                warnings.append(f"{name}: {result['detail']}")

        # System is ready if no critical errors
        ready = len(errors) == 0

        if ready:
            logger.info("InsAIts readiness check PASSED")
        else:
            logger.warning(
                "InsAIts readiness check FAILED: %s",
                "; ".join(errors),
            )

        return {
            "ready": ready,
            "checks": checks,
            "warnings": warnings,
            "errors": errors,
            "timestamp": time.time(),
        }

    def _check_license(self) -> Dict[str, Any]:
        """Check API key validation status and tier."""
        try:
            license_mgr = getattr(self._monitor, "license", None)
            if license_mgr is None:
                return _make_check(
                    "fail",
                    "LicenseManager not initialized",
                    critical=True,
                )

            tier = getattr(license_mgr, "tier", "anonymous")
            is_validated = getattr(license_mgr, "is_validated", False)
            api_key = getattr(license_mgr, "api_key", None)

            if api_key is None:
                return _make_check(
                    "warn",
                    "No API key configured. Running as anonymous "
                    "(50 msg/day limit). Register at "
                    "https://github.com/Nomadu27/InsAIts.API",
                    critical=False,
                )

            if is_validated:
                return _make_check(
                    "ok",
                    f"Validated. Tier: {tier}",
                    critical=False,
                )

            return _make_check(
                "warn",
                f"API key present but not yet validated. Tier: {tier}",
                critical=False,
            )

        except Exception as exc:
            return _make_check(
                "fail",
                f"License check error: {exc}",
                critical=True,
            )

    def _check_local_embeddings(self) -> Dict[str, Any]:
        """Check if local embedding model is loaded."""
        try:
            from . import embeddings

            if getattr(embeddings, "LOCAL_MODEL_AVAILABLE", False):
                return _make_check(
                    "ok",
                    "sentence-transformers model loaded "
                    "(BAAI/bge-small-en-v1.5, 384-dim)",
                    critical=False,
                )

            return _make_check(
                "warn",
                "Using synthetic embeddings (lower quality). "
                "Install sentence-transformers for better detection: "
                "pip install sentence-transformers",
                critical=False,
            )

        except Exception as exc:
            return _make_check(
                "fail",
                f"Embedding subsystem error: {exc}",
                critical=True,
            )

    def _check_ollama(self) -> Dict[str, Any]:
        """Check if Ollama local LLM is reachable."""
        try:
            from .local_llm import check_ollama_available, get_default_model

            if check_ollama_available():
                model = get_default_model()
                return _make_check(
                    "ok",
                    f"Ollama reachable. Default model: {model}",
                    critical=False,
                )

            return _make_check(
                "warn",
                "Ollama not running. Low-confidence detection and "
                "self-consistency checks will be disabled. "
                "Install: https://ollama.com",
                critical=False,
            )

        except ImportError:
            return _make_check(
                "warn",
                "Ollama module not available",
                critical=False,
            )
        except Exception as exc:
            return _make_check(
                "warn",
                f"Ollama check error: {exc}",
                critical=False,
            )

    def _check_cloud(self) -> Dict[str, Any]:
        """Check API backend reachability."""
        try:
            from .config import API_BASE_URL

            try:
                import requests

                response = requests.get(
                    f"{API_BASE_URL}/api/health",
                    timeout=5,
                )
                if response.status_code == 200:
                    return _make_check(
                        "ok",
                        f"API reachable at {API_BASE_URL}",
                        critical=False,
                    )
                return _make_check(
                    "warn",
                    f"API returned status {response.status_code}",
                    critical=False,
                )
            except ImportError:
                return _make_check(
                    "warn",
                    "requests not installed, cannot check cloud",
                    critical=False,
                )
            except Exception as exc:
                return _make_check(
                    "warn",
                    f"API unreachable: {exc}. Offline mode active.",
                    critical=False,
                )

        except Exception as exc:
            return _make_check(
                "warn",
                f"Cloud config error: {exc}",
                critical=False,
            )

    def _check_anomaly_engine(self) -> Dict[str, Any]:
        """Check detector initialization state."""
        try:
            detector = getattr(self._monitor, "detector", None)
            if detector is None:
                return _make_check(
                    "fail",
                    "AnomalyDetector not initialized",
                    critical=True,
                )

            premium = getattr(detector, "_premium_detector", None)
            adaptive = getattr(detector, "_adaptive_dict", None)
            anchor = getattr(detector, "_detect_anchor_drift", None)

            features = []
            features.append("fingerprint_mismatch")
            if premium is not None:
                features.append("premium_detection")
            if adaptive is not None:
                features.append("adaptive_dictionary")
            if anchor is not None:
                features.append("anchor_forensics")

            return _make_check(
                "ok",
                f"Active detectors: {', '.join(features)}",
                critical=False,
            )

        except Exception as exc:
            return _make_check(
                "fail",
                f"Anomaly engine error: {exc}",
                critical=True,
            )

    def _check_storage(self) -> Dict[str, Any]:
        """Check disk write access for caches and audit logs."""
        try:
            cache_dir = Path.home() / ".insaits"

            # Check if we can write to cache directory
            if cache_dir.exists():
                test_file = cache_dir / ".readiness_check"
                try:
                    test_file.write_text("ok")
                    test_file.unlink()
                    return _make_check(
                        "ok",
                        f"Cache directory writable: {cache_dir}",
                        critical=False,
                    )
                except (OSError, PermissionError) as exc:
                    return _make_check(
                        "warn",
                        f"Cache directory not writable: {exc}",
                        critical=False,
                    )
            else:
                # Try to create it
                try:
                    cache_dir.mkdir(parents=True, exist_ok=True)
                    return _make_check(
                        "ok",
                        f"Cache directory created: {cache_dir}",
                        critical=False,
                    )
                except (OSError, PermissionError) as exc:
                    return _make_check(
                        "warn",
                        f"Cannot create cache directory: {exc}",
                        critical=False,
                    )

        except Exception as exc:
            return _make_check(
                "warn",
                f"Storage check error: {exc}",
                critical=False,
            )
