# Copyright (c) 2026 Beijing Volcano Engine Technology Co., Ltd.
# SPDX-License-Identifier: AGPL-3.0
"""
Debug Service - provides system status query and health check.
"""

from dataclasses import dataclass
from typing import Any, Dict, List, Optional

from openviking.server.identity import RequestContext
from openviking.storage import VikingDBManager
from openviking.storage.observers import (
    FilesystemObserver,
    LockObserver,
    ModelsObserver,
    QueueObserver,
    RetrievalObserver,
    VikingDBObserver,
)
from openviking.storage.queuefs import get_queue_manager
from openviking.storage.transaction import get_lock_manager
from openviking_cli.utils.config import OpenVikingConfig
from openviking_cli.utils.logger import get_logger

logger = get_logger(__name__)


@dataclass
class ComponentStatus:
    """Component status."""

    name: str
    is_healthy: bool
    has_errors: bool
    status: str

    def __str__(self) -> str:
        health = "healthy" if self.is_healthy else "unhealthy"
        return f"[{self.name}] ({health})\n{self.status}"


@dataclass
class SystemStatus:
    """System overall status."""

    is_healthy: bool
    components: Dict[str, ComponentStatus]
    errors: List[str]

    def __str__(self) -> str:
        lines = []
        for component in self.components.values():
            lines.append(str(component))
            lines.append("")
        health = "healthy" if self.is_healthy else "unhealthy"
        lines.append(f"[system] ({health})")
        if self.errors:
            lines.append(f"Errors: {', '.join(self.errors)}")
        return "\n".join(lines)


class ObserverService:
    """Observer service - provides component status observation."""

    def __init__(
        self,
        vikingdb: Optional[VikingDBManager] = None,
        config: Optional[OpenVikingConfig] = None,
        agfs_client: Optional[Any] = None,
    ):
        self._vikingdb = vikingdb
        self._config = config
        self._agfs_client = agfs_client

    def set_dependencies(
        self,
        vikingdb: VikingDBManager,
        config: OpenVikingConfig,
        agfs_client: Optional[Any] = None,
    ) -> None:
        """Set dependencies after initialization."""
        self._vikingdb = vikingdb
        self._config = config
        if agfs_client is not None:
            self._agfs_client = agfs_client

    @property
    def _dependencies_ready(self) -> bool:
        """Check if both vikingdb and config dependencies are set."""
        return self._vikingdb is not None and self._config is not None

    @property
    def queue(self) -> ComponentStatus:
        """Get queue status."""
        try:
            qm = get_queue_manager()
        except Exception:
            return ComponentStatus(
                name="queue",
                is_healthy=False,
                has_errors=True,
                status="Not initialized",
            )
        observer = QueueObserver(qm)
        return ComponentStatus(
            name="queue",
            is_healthy=observer.is_healthy(),
            has_errors=observer.has_errors(),
            status=observer.get_status_table(),
        )

    def vikingdb(self, ctx: Optional[RequestContext] = None) -> ComponentStatus:
        """Get VikingDB status."""
        if self._vikingdb is None:
            return ComponentStatus(
                name="vikingdb",
                is_healthy=False,
                has_errors=True,
                status="Not initialized",
            )
        observer = VikingDBObserver(self._vikingdb)
        return ComponentStatus(
            name="vikingdb",
            is_healthy=observer.is_healthy(),
            has_errors=observer.has_errors(),
            status=observer.get_status_table(ctx=ctx),
        )

    @property
    def models(self) -> ComponentStatus:
        """Get Models status (VLM, Embedding, Rerank)."""
        if self._config is None:
            return ComponentStatus(
                name="models",
                is_healthy=False,
                has_errors=True,
                status="Not initialized",
            )

        vlm_instance = self._config.vlm.get_vlm_instance()
        embedding_instance = None
        rerank_instance = None

        # Get embedding instance if available
        if self._config.embedding:
            embedding_instance = self._config.embedding.get_embedder()

        # Get rerank instance if available
        if self._config.rerank and self._config.rerank.is_available():
            from openviking.models.rerank import RerankClient

            rerank_instance = RerankClient.from_config(self._config.rerank)

        observer = ModelsObserver(
            vlm_instance=vlm_instance,
            embedding_instance=embedding_instance,
            rerank_instance=rerank_instance,
        )
        return ComponentStatus(
            name="models",
            is_healthy=observer.is_healthy(),
            has_errors=observer.has_errors(),
            status=observer.get_status_table(),
        )

    @property
    def lock(self) -> ComponentStatus:
        """Get lock system status."""
        try:
            lock_manager = get_lock_manager()
        except Exception:
            return ComponentStatus(
                name="lock",
                is_healthy=False,
                has_errors=True,
                status="Not initialized",
            )
        observer = LockObserver(lock_manager)
        return ComponentStatus(
            name="lock",
            is_healthy=observer.is_healthy(),
            has_errors=observer.has_errors(),
            status=observer.get_status_table(),
        )

    @property
    def retrieval(self) -> ComponentStatus:
        """Get retrieval quality status."""
        observer = RetrievalObserver()
        return ComponentStatus(
            name="retrieval",
            is_healthy=observer.is_healthy(),
            has_errors=observer.has_errors(),
            status=observer.get_status_table(),
        )

    @property
    def filesystem(self) -> ComponentStatus:
        """Get filesystem operation status."""
        observer = FilesystemObserver()
        return ComponentStatus(
            name="filesystem",
            is_healthy=observer.is_healthy(),
            has_errors=observer.has_errors(),
            status=observer.get_status_table(),
        )

    async def get_filesystem_stats(self, mount_path: Optional[str] = None) -> dict:
        """
        Get filesystem statistics from RAGFS.

        Args:
            mount_path: Optional specific mount path.

        Returns:
            Statistics data.
        """
        try:
            if self._agfs_client is None:
                logger.debug("RAGFS client not available, returning empty stats")
                return {}

            # Call get_stats on the RAGFS client
            import asyncio
            stats = await asyncio.to_thread(
                self._agfs_client.get_stats,
                mount_path
            )
            return stats
        except Exception as e:
            logger.error(f"Error getting filesystem stats: {e}")
            return {}

    def system(self, ctx: Optional[RequestContext] = None) -> SystemStatus:
        """Get system overall status."""
        components = {
            "queue": self.queue,
            "vikingdb": self.vikingdb(ctx=ctx),
            "models": self.models,
            "lock": self.lock,
            "retrieval": self.retrieval,
            "filesystem": self.filesystem,
        }
        errors = [f"{c.name} has errors" for c in components.values() if c.has_errors]
        return SystemStatus(
            is_healthy=all(c.is_healthy for c in components.values()),
            components=components,
            errors=errors,
        )

    def is_healthy(self) -> bool:
        """Quick health check."""
        if not self._dependencies_ready:
            return False
        return self.system().is_healthy


class DebugService:
    """Debug service - provides system status query and health check."""

    def __init__(
        self,
        vikingdb: Optional[VikingDBManager] = None,
        config: Optional[OpenVikingConfig] = None,
        agfs_client: Optional[Any] = None,
    ):
        self._observer = ObserverService(vikingdb, config, agfs_client)

    def set_dependencies(
        self,
        vikingdb: VikingDBManager,
        config: OpenVikingConfig,
        agfs_client: Optional[Any] = None,
    ) -> None:
        """Set dependencies after initialization."""
        self._observer.set_dependencies(vikingdb, config, agfs_client)

    @property
    def observer(self) -> ObserverService:
        """Get observer service."""
        return self._observer

    def is_healthy(self) -> bool:
        """Quick health check."""
        return self._observer.is_healthy()
