  # #region health_service [C:3] [TYPE Module] [SEMANTICS sqlalchemy, health, dashboard, validation, aggregate]
  # @defgroup Services Module group.
  # @BRIEF Business logic for aggregating dashboard health status from validation records.
  # @LAYER Service
  # @RELATION DEPENDS_ON -> [ValidationRecord]
  # @RELATION DEPENDS_ON -> [SupersetClient]
  # @RELATION DEPENDS_ON -> [TaskCleanupService]
  # @RELATION DEPENDS_ON -> [TaskManager]
  
> from datetime import UTC
> import json
> import os
> import time
> from typing import Any, cast
  
> from sqlalchemy import func
> from sqlalchemy.orm import Session
  
> from ..core.logger import logger
> from ..core.task_manager import TaskManager
> from ..core.utils.client_registry import get_superset_client
> from ..core.task_manager.cleanup import TaskCleanupService
> from ..models.llm import ValidationRecord
> from ..schemas.health import DashboardHealthItem, HealthSummaryResponse
  
  
> def _empty_dashboard_meta() -> dict[str, str | None]:
>     return cast(dict[str, str | None], {"slug": None, "title": None})
  
  
  # #region HealthService [C:4] [TYPE Class]
  # @defgroup Services Module group.
  # @BRIEF Aggregate latest dashboard validation state and manage persisted health report lifecycle.
  # @PRE  Service is constructed with a live SQLAlchemy session and optional config manager.
  # @POST  Exposes health summary aggregation and validation report deletion operations.
  # @SIDE_EFFECT  Maintains in-memory dashboard metadata caches and may coordinate cleanup through collaborators.
  # @DATA_CONTRACT  Input[Session, Optional[Any]] -> Output[HealthSummaryResponse|bool]
  # @RELATION DEPENDS_ON -> [ValidationRecord]
  # @RELATION DEPENDS_ON -> [DashboardHealthItem]
  # @RELATION DEPENDS_ON -> [HealthSummaryResponse]
  # @RELATION DEPENDS_ON -> [SupersetClient]
  # @RELATION DEPENDS_ON -> [TaskCleanupService]
  # @RELATION DEPENDS_ON -> [TaskManager]
> class HealthService:
>     _dashboard_summary_cache: dict[
>         str, tuple[float, dict[str, dict[str, str | None]]]
>     ] = {}
>     _dashboard_summary_cache_ttl_seconds = 60.0
  
>     """
>     @PURPOSE: Service for managing and querying dashboard health data.
>     """
  
      # region HealthService_init [TYPE Function]
      # @PURPOSE: Initialize health service with DB session and optional config access for dashboard metadata resolution.
      # @PRE  db is a valid SQLAlchemy session.
      # @POST  Service is ready to aggregate summaries and delete health reports.
      # @SIDE_EFFECT  Initializes per-instance dashboard metadata cache.
      # @DATA_CONTRACT  Input[db: Session, config_manager: Optional[Any]] -> Output[HealthService]
      # @RELATION BINDS_TO ->[HealthService]
>     def __init__(self, db: Session, config_manager=None):
>         self.db = db
>         self.config_manager = config_manager
>         self._dashboard_meta_cache: dict[tuple[str, str], dict[str, str | None]] = {}
  
      # endregion HealthService_init
  
      # region _prime_dashboard_meta_cache [TYPE Function]
      # @PURPOSE: Warm dashboard slug/title cache with one Superset list fetch per environment.
      # @PRE  records may contain mixed numeric and slug dashboard identifiers.
      # @POST  Numeric dashboard ids for known environments are cached when discoverable.
      # @SIDE_EFFECT  May call Superset dashboard list API once per referenced environment.
      # @DATA_CONTRACT  Input[records: List[ValidationRecord]] -> Output[None]
      # @RELATION DEPENDS_ON ->[ValidationRecord]
      # @RELATION DEPENDS_ON ->[ConfigManager]
      # @RELATION DEPENDS_ON ->[SupersetClient]
>     async def _prime_dashboard_meta_cache(self, records: list[ValidationRecord]) -> None:
>         if not self.config_manager or not records:
!             return
  
>         numeric_ids_by_env: dict[str, set[str]] = {}
>         for record in records:
>             environment_id = str(record.environment_id or "").strip()
>             dashboard_id = str(record.dashboard_id or "").strip()
>             if not environment_id or not dashboard_id or not dashboard_id.isdigit():
!                 continue
>             cache_key = (environment_id, dashboard_id)
>             if cache_key in self._dashboard_meta_cache:
!                 continue
>             numeric_ids_by_env.setdefault(environment_id, set()).add(dashboard_id)
  
>         if not numeric_ids_by_env:
!             return
  
>         environments = {
>             str(getattr(env, "id", "")).strip(): env
>             for env in self.config_manager.get_environments()
>             if str(getattr(env, "id", "")).strip()
>         }
  
>         for environment_id, dashboard_ids in numeric_ids_by_env.items():
>             env = environments.get(environment_id)
>             if not env:
!                 for dashboard_id in dashboard_ids:
!                     self._dashboard_meta_cache[(environment_id, dashboard_id)] = (
!                         _empty_dashboard_meta()
!                     )
!                 continue
  
>             try:
>                 cached_meta = self.__class__._dashboard_summary_cache.get(
>                     environment_id
>                 )
>                 dashboard_meta_map: dict[str, dict[str, str | None]]
>                 if (
>                     cached_meta is not None
>                     and (time.monotonic() - cached_meta[0])
>                     < self.__class__._dashboard_summary_cache_ttl_seconds
>                 ):
!                     cached_meta_data = cast(
!                         tuple[float, dict[str, dict[str, str | None]]],
!                         cached_meta,
!                     )
!                     dashboard_meta_map = cached_meta_data[1]
>                 else:
>                     client = await get_superset_client(env)
>                     dashboards = await client.get_dashboards_summary()
>                     dashboard_meta_map = {
>                         str(item.get("id")): {
>                             "slug": item.get("slug"),
>                             "title": item.get("title"),
>                         }
>                         for item in dashboards
>                         if str(item.get("id") or "").strip()
>                     }
>                     self.__class__._dashboard_summary_cache[environment_id] = (
>                         time.monotonic(),
>                         dashboard_meta_map,
>                     )
>                 for dashboard_id in dashboard_ids:
>                     self._dashboard_meta_cache[(environment_id, dashboard_id)] = (
>                         dashboard_meta_map.get(
>                             dashboard_id,
>                             _empty_dashboard_meta(),
>                         )
>                     )
!             except Exception as exc:
!                 logger.warning(
!                     "[HealthService][EXT:method:_prime_dashboard_meta_cache] Failed to preload dashboard metadata for env=%s: %s",
!                     environment_id,
!                     exc,
!                 )
!                 for dashboard_id in dashboard_ids:
!                     self._dashboard_meta_cache[(environment_id, dashboard_id)] = (
!                         _empty_dashboard_meta()
!                     )
  
      # endregion _prime_dashboard_meta_cache
  
      # region _resolve_dashboard_meta [TYPE Function]
      # @PURPOSE: Resolve slug/title for a dashboard referenced by persisted validation record.
      # @PRE  dashboard_id may be numeric or slug-like; environment_id may be empty.
      # @POST  Returns dict with `slug` and `title` keys, using cache when possible.
      # @SIDE_EFFECT  Writes default cache entries for unresolved numeric dashboard ids.
>     def _resolve_dashboard_meta(
>         self, dashboard_id: str, environment_id: str | None
>     ) -> dict[str, str | None]:
>         normalized_dashboard_id = str(dashboard_id or "").strip()
>         normalized_environment_id = str(environment_id or "").strip()
>         if not normalized_dashboard_id:
!             return _empty_dashboard_meta()
  
>         if not normalized_dashboard_id.isdigit():
!             return {"slug": normalized_dashboard_id, "title": None}
  
>         if not self.config_manager or not normalized_environment_id:
!             return _empty_dashboard_meta()
  
>         cache_key = (normalized_environment_id, normalized_dashboard_id)
>         cached = self._dashboard_meta_cache.get(cache_key)
>         if cached is not None:
>             return cached
  
!         meta = _empty_dashboard_meta()
!         self._dashboard_meta_cache[cache_key] = meta
!         return meta
  
      # endregion _resolve_dashboard_meta
  
      # region get_health_summary [TYPE Function]
      # @PURPOSE: Aggregate latest validation status per dashboard and enrich rows with dashboard slug/title.
      # @PRE  environment_id may be omitted to aggregate across all environments.
      # @POST  Returns HealthSummaryResponse with counts and latest record row per dashboard.
      # @SIDE_EFFECT  May call Superset API to resolve dashboard metadata.
      # @DATA_CONTRACT  Input[environment_id: Optional[str]] -> Output[HealthSummaryResponse]
      # @RELATION CALLS ->[EXT:method:_prime_dashboard_meta_cache]
      # @RELATION CALLS ->[EXT:method:_resolve_dashboard_meta]
>     async def get_health_summary(
>         self, environment_id: str = ""
>     ) -> HealthSummaryResponse:
>         """
>         @PURPOSE: Aggregates the latest validation status for all dashboards.
>         @PRE: environment_id (optional) to filter by environment.
>         @POST: Returns a HealthSummaryResponse with aggregated status counts and items.
>         """
          # [REASON] We need the latest ValidationRecord for each unique dashboard_id.
          # We use a subquery to find the max timestamp per dashboard_id.
  
>         subquery = self.db.query(
>             ValidationRecord.dashboard_id,
>             func.max(ValidationRecord.timestamp).label("max_ts"),
>         )
>         if environment_id:
>             subquery = subquery.filter(
>                 ValidationRecord.environment_id == environment_id
>             )
>         subquery = subquery.group_by(ValidationRecord.dashboard_id).subquery()
  
>         query = self.db.query(ValidationRecord).join(
>             subquery,
>             (ValidationRecord.dashboard_id == subquery.c.dashboard_id)
>             & (ValidationRecord.timestamp == subquery.c.max_ts),
>         )
  
>         records = query.all()
  
>         await self._prime_dashboard_meta_cache(records)
  
>         items = []
>         pass_count = 0
>         warn_count = 0
>         fail_count = 0
>         unknown_count = 0
  
>         for rec in records:
>             record = cast(Any, rec)
>             status = str(record.status or "").upper()
>             if status == "PASS":
>                 pass_count += 1
!             elif status == "WARN":
!                 warn_count += 1
!             elif status == "FAIL":
!                 fail_count += 1
!             else:
!                 unknown_count += 1
!                 status = "UNKNOWN"
  
>             record_id = str(record.id or "")
>             dashboard_id = str(record.dashboard_id or "")
>             resolved_environment_id = (
>                 str(record.environment_id)
>                 if record.environment_id is not None
>                 else None
>             )
>             response_environment_id = (
>                 resolved_environment_id
>                 if resolved_environment_id is not None
>                 else "unknown"
>             )
>             task_id = str(record.task_id) if record.task_id is not None else None
>             summary = str(record.summary) if record.summary is not None else None
>             timestamp = cast(Any, record.timestamp)
              # Ensure timestamp is timezone-aware (DB stores naive UTC)
>             if timestamp is not None and timestamp.tzinfo is None:
!                 timestamp = timestamp.replace(tzinfo=UTC)
  
              # ── v2 fields ──────────────────────────────────────────────
>             execution_path = str(record.execution_path) if record.execution_path else None
>             issues_count = len(record.issues) if record.issues else 0
>             timings = dict(record.timings) if record.timings else None
>             token_usage = dict(record.token_usage) if record.token_usage else None
>             screenshot_paths = list(record.screenshot_paths) if record.screenshot_paths else None
  
              # Extract chunk_count from raw_response (stored as JSON in result_payload)
>             chunk_count: int | None = None
>             if record.raw_response:
!                 try:
!                     raw = json.loads(record.raw_response)
!                     chunk_count = int(raw["chunk_count"]) if raw.get("chunk_count") else None
!                 except (json.JSONDecodeError, KeyError, TypeError, ValueError):
!                     pass
  
>             meta = self._resolve_dashboard_meta(dashboard_id, resolved_environment_id)
>             dashboard_name = meta.get("title") or meta.get("slug") or dashboard_id
>             items.append(
>                 DashboardHealthItem(
>                     record_id=record_id,
>                     dashboard_id=dashboard_id,
>                     dashboard_slug=meta.get("slug"),
>                     dashboard_title=meta.get("title"),
>                     environment_id=response_environment_id,
>                     status=status,
>                     last_check=timestamp,
>                     task_id=task_id,
>                     run_id=str(record.run_id) if record.run_id else None,
>                     policy_id=str(record.policy_id) if record.policy_id else None,
>                     summary=summary,
>                     execution_path=execution_path,
>                     issues_count=issues_count,
>                     timings=timings,
>                     token_usage=token_usage,
>                     screenshot_paths=screenshot_paths,
>                     chunk_count=chunk_count,
>                     dashboard_name=dashboard_name,
>                 )
>             )
  
>         logger.info(
>             f"[HealthService][get_health_summary] Aggregated {len(items)} dashboard health records."
>         )
  
>         return HealthSummaryResponse(
>             items=items,
>             pass_count=pass_count,
>             warn_count=warn_count,
>             fail_count=fail_count,
>             unknown_count=unknown_count,
>         )
  
      # endregion get_health_summary
  
      # region delete_validation_report [TYPE Function]
      # @PURPOSE: Delete one persisted health report and optionally clean linked task/log artifacts.
      # @PRE  record_id is a validation record identifier.
      # @POST  Returns True only when a matching record was deleted.
      # @SIDE_EFFECT  Deletes DB rows, optional screenshot file, and optional task/log persistence.
      # @DATA_CONTRACT  Input[record_id: str, task_manager: Optional[TaskManager]] -> Output[bool]
      # @RELATION DEPENDS_ON ->[ValidationRecord]
      # @RELATION DEPENDS_ON ->[TaskManager]
      # @RELATION DEPENDS_ON ->[TaskCleanupService]
>     def delete_validation_report(
>         self, record_id: str, task_manager: TaskManager | None = None
>     ) -> bool:
!         record = (
!             self.db.query(ValidationRecord)
!             .filter(ValidationRecord.id == record_id)
!             .first()
!         )
!         if not record:
!             return False
  
!         peer_query = self.db.query(ValidationRecord).filter(
!             ValidationRecord.dashboard_id == record.dashboard_id
!         )
!         if record.environment_id is None:
!             peer_query = peer_query.filter(ValidationRecord.environment_id.is_(None))
!         else:
!             peer_query = peer_query.filter(
!                 ValidationRecord.environment_id == record.environment_id
!             )
  
!         records_to_delete = peer_query.all()
!         screenshot_paths = [
!             str(item.screenshot_path or "").strip()
!             for item in records_to_delete
!             if str(item.screenshot_path or "").strip()
!         ]
!         task_ids = {
!             str(item.task_id or "").strip()
!             for item in records_to_delete
!             if str(item.task_id or "").strip()
!         }
  
!         logger.info(
!             "[HealthService][delete_validation_report] Removing %s validation record(s) for dashboard=%s environment=%s triggered_by_record=%s",
!             len(records_to_delete),
!             record.dashboard_id,
!             record.environment_id,
!             record_id,
!         )
  
!         for item in records_to_delete:
!             self.db.delete(item)
!         self.db.commit()
  
!         for screenshot_path in screenshot_paths:
!             try:
!                 if os.path.exists(screenshot_path):
!                     os.remove(screenshot_path)
!             except OSError as exc:
!                 logger.warning(
!                     "[HealthService][delete_validation_report] Failed to remove screenshot %s: %s",
!                     screenshot_path,
!                     exc,
!                 )
  
!         if task_ids and task_manager and self.config_manager:
!             try:
!                 cleanup_service = TaskCleanupService(
!                     task_manager.persistence_service,
!                     task_manager.log_persistence_service,
!                     self.config_manager,
!                 )
!                 for task_id in task_ids:
!                     task_manager.tasks.pop(task_id, None)
!                     cleanup_service.delete_task_with_logs(task_id)
!             except Exception as exc:
!                 logger.warning(
!                     "[HealthService][delete_validation_report] Failed to cleanup linked task/logs for dashboard=%s environment=%s: %s",
!                     record.dashboard_id,
!                     record.environment_id,
!                     exc,
!                 )
  
!         return True
  
      # endregion delete_validation_report
  
  
  # #endregion HealthService
  
  # #endregion health_service
