# #region superset_lookup_service [C:4] [TYPE Module] [SEMANTICS superset,account,lookup,environment]
# @BRIEF Environment-scoped Superset account lookup with degradation fallback for network failures.
# @LAYER Domain
# @RELATION DEPENDS_ON -> [SupersetClient]
# @RELATION DEPENDS_ON -> [SupersetAccountLookupAdapter]
# @RELATION DEPENDS_ON -> [ProfileUtils]
# @RATIONALE Extracted from ProfileService to satisfy INV_7. Superset account lookup has distinct
#            I/O patterns (external HTTP calls, environment resolution) that isolate cleanly from
#            preference persistence and security badge logic.
# @REJECTED Keeping lookup inside ProfileService was rejected — it adds network I/O and
#            environment coupling to preference operations that only need DB access, and inflates
#            the class past 150 lines.
# @PRE current_user is authenticated; environment_id must be resolvable.
# @POST Returns success or degraded SupersetAccountLookupResponse with stable shape.
# @SIDE_EFFECT Performs external Superset HTTP calls via SupersetClient + adapter.
# @RAISES EnvironmentNotFoundError when environment_id is unknown.

from typing import Any

from ..core.logger import belief_scope, logger
from ..core.superset_client import SupersetClient
from ..core.superset_profile_lookup import SupersetAccountLookupAdapter
from ..schemas.profile import (
    SupersetAccountCandidate,
    SupersetAccountLookupRequest,
    SupersetAccountLookupResponse,
)
from .profile_utils import EnvironmentNotFoundError


# #region SupersetLookupService [C:4] [TYPE Class] [SEMANTICS superset,lookup,environment,degradation]
# @BRIEF Resolves environments and queries Superset users in selected environment,
#        returning canonical account candidates with degradation fallback.
# @RELATION DEPENDS_ON -> [SupersetClient]
# @RELATION DEPENDS_ON -> [SupersetAccountLookupAdapter]
# @RELATION CALLS -> [SupersetClient]
# @PRE config_manager supports get_environments().
# @POST lookup_superset_accounts returns success payload or degraded payload with warning.
class SupersetLookupService:
    """Environment-scoped Superset account lookup with degradation fallback."""

    # #region __init__ [TYPE Function]
    # @BRIEF Initialize with config manager for environment resolution.
    def __init__(self, config_manager: Any):
        self.config_manager = config_manager
    # #endregion __init__

    # #region lookup_superset_accounts [TYPE Function]
    # @BRIEF Query Superset users in selected environment and project canonical account candidates.
    # @PRE current_user is authenticated and environment_id exists.
    # @POST Returns success payload or degraded payload with warning while preserving manual fallback.
    def lookup_superset_accounts(
        self,
        current_user: Any,
        request: SupersetAccountLookupRequest,
    ) -> SupersetAccountLookupResponse:
        with belief_scope(
            "SupersetLookupService.lookup_superset_accounts",
            f"user_id={getattr(current_user, 'id', '?')}, environment_id={request.environment_id}",
        ):
            environment = self._resolve_environment(request.environment_id)
            if environment is None:
                logger.explore("Lookup aborted: environment not found")
                raise EnvironmentNotFoundError(
                    f"Environment '{request.environment_id}' not found"
                )

            sort_column = str(request.sort_column or "username").strip().lower()
            sort_order = str(request.sort_order or "desc").strip().lower()
            allowed_columns = {"username", "first_name", "last_name", "email"}
            if sort_column not in allowed_columns:
                sort_column = "username"
            if sort_order not in {"asc", "desc"}:
                sort_order = "desc"

            logger.reflect(
                "Normalized lookup request "
                f"(env={request.environment_id}, sort_column={sort_column}, sort_order={sort_order}, "
                f"page_index={request.page_index}, page_size={request.page_size}, "
                f"search={(request.search or '').strip()!r})"
            )

            try:
                logger.reason("Performing Superset account lookup")
                superset_client = SupersetClient(environment)
                adapter = SupersetAccountLookupAdapter(
                    network_client=superset_client.network,
                    environment_id=request.environment_id,
                )
                lookup_result = adapter.get_users_page(
                    search=request.search,
                    page_index=request.page_index,
                    page_size=request.page_size,
                    sort_column=sort_column,
                    sort_order=sort_order,
                )
                items = [
                    SupersetAccountCandidate.model_validate(item)
                    for item in lookup_result.get("items", [])
                ]
                return SupersetAccountLookupResponse(
                    status="success",
                    environment_id=request.environment_id,
                    page_index=request.page_index,
                    page_size=request.page_size,
                    total=max(int(lookup_result.get("total", len(items))), 0),
                    warning=None,
                    items=items,
                )
            except Exception as exc:
                logger.explore(
                    f"Lookup degraded due to upstream error: {exc}"
                )
                return SupersetAccountLookupResponse(
                    status="degraded",
                    environment_id=request.environment_id,
                    page_index=request.page_index,
                    page_size=request.page_size,
                    total=0,
                    warning=(
                        "Cannot load Superset accounts for this environment right now. "
                        "You can enter username manually."
                    ),
                    items=[],
                )
    # #endregion lookup_superset_accounts

    # #region _resolve_environment [C:2] [TYPE Function]
    # @BRIEF Resolve environment model from configured environments by id.
    # @PRE environment_id is provided.
    # @POST Returns environment object when found else None.
    def _resolve_environment(self, environment_id: str):
        environments = self.config_manager.get_environments()
        for env in environments:
            if str(getattr(env, "id", "")) == str(environment_id):
                return env
        return None
    # #endregion _resolve_environment
# #endregion SupersetLookupService
# #endregion superset_lookup_service
