"""Main client class for Questra Automation."""

from __future__ import annotations

from loguru import logger
from questra_authentication import QuestraAuthentication

from .operations import MutationOperations, QueryOperations
from .transport import GraphQLTransport


class QuestraAutomation:
    """
    Client for Questra Automation GraphQL API.

    Uses an existing QuestraAuthentication for authentication
    and provides a type-safe interface to the Automation GraphQL API.

    Examples:
        ```python
        from questra_authentication import QuestraAuthentication
        from questra_automation import QuestraAutomation

        # Create QuestraAuthentication
        auth_client = QuestraAuthentication(
            url="https://authentik.dev.example.com",
            username="ServiceUser",
            password="secret_password",
            oidc_discovery_paths=["/application/o/automation"],
        )

        # Initialize QuestraAutomation with QuestraAuthentication
        automation = QuestraAutomation(
            graphql_url="https://automation.dev.example.com/graphql",
            auth_client=auth_client,
        )

        # Query workspaces
        workspaces = automation.queries.get_workspaces(first=10)
        for workspace in workspaces.nodes:
            print(f"Workspace: {workspace.name}")

        # Execute an automation
        result = automation.mutations.execute_automation(
            workspace_name="my-workspace",
            automation_path="scripts/my_automation.py",
            initiator_type=ExecutionInitiator.MANUAL,
            arguments=[{"name": "param1", "value": "value1"}],
        )
        print(f"Execution ID: {result.id}")
        ```
    """

    def __init__(
        self,
        graphql_url: str,
        auth_client: QuestraAuthentication,
    ):
        """
        Initialize the QuestraAutomation client.

        Args:
            graphql_url: URL of the GraphQL endpoint
            auth_client: Configured and authenticated QuestraAuthentication

        Raises:
            ValueError: If auth_client is not authenticated
        """
        logger.info("Initializing QuestraAutomation", graphql_url=graphql_url)

        self._graphql_url = graphql_url
        self._auth_client = auth_client

        if not self._auth_client.is_authenticated():
            logger.error("QuestraAuthentication is not authenticated")
            raise ValueError(
                "QuestraAuthentication is not authenticated. "
                "Please authenticate the client before passing it."
            )

        logger.debug("QuestraAuthentication authentication verified")

        self._transport = GraphQLTransport(
            url=graphql_url,
            get_access_token_func=self._auth_client.get_access_token,
        )

        self._queries = QueryOperations(execute_func=self._transport.execute)
        self._mutations = MutationOperations(execute_func=self._transport.execute)

        logger.info("QuestraAutomation initialized successfully")

    @property
    def queries(self) -> QueryOperations:
        """
        Access to query operations.

        Returns:
            QueryOperations instance for queries

        Examples:
            ```python
            # Get all workspaces
            workspaces = client.queries.get_workspaces(first=10)

            # Get executions with filter
            executions = client.queries.get_executions(
                first=10,
                where={"status": {"eq": "SUCCEEDED"}},
            )

            # Get service info
            info = client.queries.get_service_info()
            print(f"Service: {info.name} v{info.version}")
            ```
        """
        return self._queries

    @property
    def mutations(self) -> MutationOperations:
        """
        Access to mutation operations.

        Returns:
            MutationOperations instance for mutations

        Examples:
            ```python
            # Execute an automation
            result = client.mutations.execute_automation(
                workspace_name="my-workspace",
                automation_path="scripts/my_automation.py",
                initiator_type=ExecutionInitiator.MANUAL,
                arguments=[{"name": "param1", "value": "value1"}],
            )

            # Create a workspace
            workspace = client.mutations.create_workspace(
                repository_name="my-repo",
                name="my-workspace",
                branch_name="main",
                commit="abc123",
            )

            # Create a schedule
            schedule = client.mutations.create_schedule(
                workspace_name="my-workspace",
                automation_path="scripts/my_automation.py",
                name="daily-run",
                description="Run daily at midnight",
                cron="0 0 * * *",
                timezone="Europe/Berlin",
                active=True,
            )
            ```
        """
        return self._mutations

    def execute_raw(self, query: str, variables: dict | None = None) -> dict:
        """
        Execute a raw GraphQL query or mutation.

        Useful for custom operations that are not covered by the standard operations.

        Args:
            query: GraphQL query or mutation string
            variables: Optional variables

        Returns:
            dict: Raw result of the GraphQL operation

        Examples:
            ```python
            result = client.execute_raw('''
                query {
                    automationServiceInfo {
                        name
                        version
                    }
                }
            ''')
            ```
        """
        logger.debug("Executing raw GraphQL operation via QuestraAutomation")
        return self._transport.execute(query, variables)

    def is_authenticated(self) -> bool:
        """
        Check if the client is authenticated.

        Returns:
            bool: True if authenticated, False otherwise
        """
        return self._auth_client.is_authenticated()

    def reauthenticate(self) -> None:
        """
        Force reauthentication.

        Useful for authentication problems or when credentials have changed.
        """
        logger.info("Forcing reauthentication")
        self._auth_client.reauthenticate()
        logger.info("Reauthentication completed")

    @property
    def graphql_url(self) -> str:
        """
        GraphQL endpoint URL.

        Returns:
            str: URL of the GraphQL endpoint
        """
        return self._graphql_url

    def __repr__(self) -> str:
        """String representation of the client."""
        auth_status = (
            "authenticated" if self.is_authenticated() else "not authenticated"
        )
        return (
            f"QuestraAutomation(graphql_url='{self._graphql_url}', "
            f"status='{auth_status}')"
        )
