"""GraphQL Query-Operationen für Questra Data."""

from __future__ import annotations

from typing import Any

from loguru import logger

from ..models import Inventory, Namespace, Role, SystemInfo, TimeZone, Unit


class QueryOperations:
    """
    Query-Operationen für Dyno GraphQL API.

    Verantwortlich für:
    - Inventories abfragen
    - Namespaces abfragen
    - Roles abfragen
    - System-Informationen abfragen
    """

    def __init__(self, execute_func: callable):
        """
        Initialisiert die Query-Operationen.

        Args:
            execute_func: Funktion zum Ausführen von GraphQL-Queries
        """
        self._execute = execute_func

    def get_inventories(
        self,
        where: dict[str, Any] | None = None,
        order: dict[str, str] | None = None,
    ) -> list[Inventory]:
        """
        Ruft eine Liste von Inventories ab.

        Args:
            where: Filter-Bedingungen (namespaceNames, inventoryNames).
                Beispiel: {"namespaceNames": ["MyNamespace"], "inventoryNames": ["MyInventory"]}
            order: Sortierung (by: NAME)

        Returns:
            list[Inventory]: Liste von Inventories (ohne Pagination)
        """
        logger.debug("Getting inventories", where=where, order=order)

        query = """
            query GetInventories(
                $where: _InventoryFilter__InputType
                $order: _InventorySort__InputType
            ) {
                _inventories(
                    where: $where
                    order: $order
                ) {
                    name
                    description
                    inventoryType
                    auditEnabled
                    createdBy
                    createdAt
                    alteredBy
                    alteredAt
                    selectFieldName
                    insertFieldName
                    updateFieldName
                    deleteFieldName
                    namespace {
                        name
                    }
                    properties {
                        name
                        fieldName
                        sortOrder
                        dataType
                        isRequired
                        isUnique
                        isArray
                        description
                        string {
                            maxLength
                            isCaseSensitive
                        }
                        file {
                            maxLength
                        }
                        timeSeries {
                            interval {
                                multiplier
                                timeUnit
                            }
                            unit
                            timeZone
                            specificsPerInstanceAllowed
                            valueAlignment
                            valueAvailability
                            defaultAggregation
                            startOfTime
                            auditEnabled
                            quotationEnabled
                            defaultQuotationBehavior
                        }
                    }
                    parentRelations {
                        relationType
                        isRequired
                    }
                    childRelations {
                        relationType
                        isRequired
                    }
                }
            }
        """

        variables = {
            "where": where,
            "order": order,
        }

        result = self._execute(query, variables)
        inventories_data = result["_inventories"]

        inventories = [Inventory.from_dict(inv_data) for inv_data in inventories_data]
        logger.info(f"Retrieved {len(inventories)} inventories")
        return inventories

    def get_namespaces(self) -> list[Namespace]:
        """
        Ruft eine Liste von Namespaces ab.

        Returns:
            list[Namespace]: Liste von Namespaces
        """
        logger.debug("Getting namespaces")

        query = """
            query GetNamespaces {
                _namespaces {
                    name
                    description
                    isSystem
                    createdBy
                    createdAt
                    alteredBy
                    alteredAt
                }
            }
        """

        result = self._execute(query)
        namespaces_data = result["_namespaces"]

        namespaces = [Namespace.from_dict(ns_data) for ns_data in namespaces_data]
        logger.info(f"Retrieved {len(namespaces)} namespaces")
        return namespaces

    def get_roles(self) -> list[Role]:
        """
        Ruft eine Liste von Roles ab.

        Returns:
            list[Role]: Liste von Roles (ohne Pagination)
        """
        logger.debug("Getting roles")

        query = """
            query GetRoles {
                _roles {
                    name
                    description
                    isSystem
                    createdBy
                    createdAt
                    alteredBy
                    alteredAt
                }
            }
        """

        result = self._execute(query)
        roles_data = result["_roles"]

        roles = [Role.from_dict(role_data) for role_data in roles_data]
        logger.info(f"Retrieved {len(roles)} roles")
        return roles

    def get_system_info(self, include_message_infos: bool = False) -> SystemInfo:
        """
        Ruft System-Informationen ab.

        Args:
            include_message_infos: Wenn True, werden messageInfos mit abgerufen

        Returns:
            SystemInfo: Objekt mit System-Informationen
        """
        logger.debug("Getting system info", include_message_infos=include_message_infos)

        message_infos_fragment = (
            """
                    messageInfos {
                        code
                        template
                        category
                    }
        """
            if include_message_infos
            else ""
        )

        query = f"""
            query GetSystemInfo {{
                _systemInfo {{
                    dynamicObjectsVersion
                    databaseVersion
                    memoryInfo {{
                        totalMb
                        usedMb
                        freeMb
                        availablePercent
                    }}{message_infos_fragment}
                }}
            }}
        """

        result = self._execute(query)
        system_info_data = result["_systemInfo"]
        system_info = SystemInfo.from_dict(system_info_data)
        logger.info(
            "Retrieved system info", version=system_info.dynamic_objects_version
        )
        return system_info

    def get_units(self) -> list[Unit]:
        """
        Ruft alle Units ab.

        Returns:
            list[Unit]: Liste von Units
        """
        logger.debug("Getting units")

        query = """
            query GetUnits {
                _units {
                    symbol
                    aggregation
                }
            }
        """

        result = self._execute(query)
        units_data = result["_units"]
        units = [Unit.from_dict(u) for u in units_data]
        logger.info(f"Retrieved {len(units)} units")
        return units

    def get_time_zones(self) -> list[TimeZone]:
        """
        Ruft alle Zeitzonen ab.

        Returns:
            list[TimeZone]: Liste von Zeitzonen
        """
        logger.debug("Getting time zones")

        query = """
            query GetTimeZones {
                _timeZones {
                    name
                    baseUtcOffset
                    supportsDaylightSavingTime
                }
            }
        """

        result = self._execute(query)
        time_zones_data = result["_timeZones"]
        time_zones = [TimeZone.from_dict(tz) for tz in time_zones_data]
        logger.info(f"Retrieved {len(time_zones)} time zones")
        return time_zones
