"""GraphQL Operations for Questra Automation."""

from __future__ import annotations

from datetime import datetime
from typing import Any
from uuid import UUID

from loguru import logger

from .models import (
    AutomationArgumentDefinition,
    AutomationArgumentInstance,
    AutomationBuildError,
    AutomationBuildStatus,
    AutomationExecutionDomainStatus,
    AutomationExecutionStatus,
    AutomationExecutionView,
    AutomationInitiatorType,
    AutomationsConnection,
    AutomationsEdge,
    AutomationView,
    CreateRepositoryPayload,
    CreateSchedulePayload,
    CreateWorkspacePayload,
    DeleteRepositoryPayload,
    DeleteSchedulePayload,
    DeleteWorkspacePayload,
    ErrorCodesConnection,
    ErrorCodesEdge,
    ErrorCodeView,
    ExecutePayload,
    ExecutionInitiator,
    ExecutionsConnection,
    ExecutionsEdge,
    KeyValuePair,
    PageInfo,
    RenewRepositorySshKeyPayload,
    RepositoriesConnection,
    RepositoriesEdge,
    RepositoryAuthenticationMethod,
    RepositoryView,
    ScheduledExecutionsConnection,
    ScheduledExecutionsEdge,
    ScheduledExecutionView,
    SchedulesConnection,
    SchedulesEdge,
    ScheduleView,
    ServiceInfo,
    SynchronizeWorkspacePayload,
    UpdateRepositoryPayload,
    UpdateSchedulePayload,
    UpdateWorkspacePayload,
    WorkspacesConnection,
    WorkspacesEdge,
    WorkspaceView,
)


def _parse_datetime(value: str | None) -> datetime | None:
    """Parse ISO-8601 datetime string."""
    if value is None:
        return None
    return datetime.fromisoformat(value.replace("Z", "+00:00"))


def _parse_page_info(data: dict) -> PageInfo:
    """Parse PageInfo from GraphQL response."""
    return PageInfo(
        has_next_page=data["hasNextPage"],
        has_previous_page=data["hasPreviousPage"],
        start_cursor=data.get("startCursor"),
        end_cursor=data.get("endCursor"),
    )


def _parse_key_value_pair(data: dict) -> KeyValuePair:
    """Parse KeyValuePair from GraphQL response."""
    return KeyValuePair(
        key=data["key"],
        value=data["value"],
    )


def _parse_automation_build_error(data: dict) -> AutomationBuildError:
    """Parse AutomationBuildError from GraphQL response."""
    return AutomationBuildError(
        code=data["code"],
        message_template=data["messageTemplate"],
        data=[_parse_key_value_pair(kv) for kv in data["data"]],
    )


def _parse_automation_argument_definition(data: dict) -> AutomationArgumentDefinition:
    """Parse AutomationArgumentDefinition from GraphQL response."""
    return AutomationArgumentDefinition(
        name=data["name"],
        description=data["description"],
        mandatory=data["mandatory"],
    )


def _parse_automation_argument_instance(data: dict) -> AutomationArgumentInstance:
    """Parse AutomationArgumentInstance from GraphQL response."""
    return AutomationArgumentInstance(
        name=data["name"],
        value=data["value"],
    )


def _parse_repository_view(data: dict) -> RepositoryView:
    """Parse RepositoryView from GraphQL response."""
    return RepositoryView(
        name=data["name"],
        url=data["url"],
        created_at=_parse_datetime(data["createdAt"]),
        changed_at=_parse_datetime(data["changedAt"]),
        authentication_method=RepositoryAuthenticationMethod(
            data["authenticationMethod"]
        ),
        username=data.get("username"),
        ssh_public_key=data.get("sshPublicKey"),
        workspaces=None,
    )


def _parse_workspace_view(data: dict) -> WorkspaceView:
    """Parse WorkspaceView from GraphQL response."""
    return WorkspaceView(
        name=data["name"],
        repository_name=data["repositoryName"],
        build_status=AutomationBuildStatus(data["buildStatus"]),
        build_errors=[
            _parse_automation_build_error(e) for e in data.get("buildErrors", [])
        ],
        build_branch=data.get("buildBranch"),
        build_commit=data.get("buildCommit"),
        build_started_at=_parse_datetime(data.get("buildStartedAt")),
        build_finished_at=_parse_datetime(data.get("buildFinishedAt")),
        build_duration=data.get("buildDuration"),
        active_branch=data.get("activeBranch"),
        active_commit=data.get("activeCommit"),
        created_at=_parse_datetime(data["createdAt"]),
        changed_at=_parse_datetime(data["changedAt"]),
        repository=(
            _parse_repository_view(data["repository"])
            if "repository" in data and data["repository"]
            else None
        ),
        automations=None,
    )


def _parse_schedule_view(data: dict) -> ScheduleView:
    """Parse ScheduleView from GraphQL response."""
    return ScheduleView(
        automation_path=data["automationPath"],
        name=data["name"],
        description=data["description"],
        cron=data["cron"],
        timezone=data["timezone"],
        active=data["active"],
        argument_instances=[
            _parse_automation_argument_instance(a)
            for a in data.get("argumentInstances", [])
        ],
        version=data["version"],
        workspace=None,
    )


def _parse_automation_view(data: dict) -> AutomationView:
    """Parse AutomationView from GraphQL response."""
    return AutomationView(
        workspace_name=data["workspaceName"],
        path=data["path"],
        description=data["description"],
        environment=data["environment"],
        allow_parallel_execution=data["allowParallelExecution"],
        argument_definitions=[
            _parse_automation_argument_definition(a)
            for a in data.get("argumentDefinitions", [])
        ],
        workspace=None,
        schedules=None,
    )


def _parse_automation_execution_view(data: dict) -> AutomationExecutionView:
    """Parse AutomationExecutionView from GraphQL response."""
    return AutomationExecutionView(
        id=UUID(data["id"]),
        branch=data["branch"],
        commit=data["commit"],
        workspace_name=data["workspaceName"],
        repository_name=data["repositoryName"],
        repository_url=data["repositoryUrl"],
        automation_path=data["automationPath"],
        environment=data["environment"],
        initiator_type=AutomationInitiatorType(data["initiatorType"]),
        initiator_reference=data.get("initiatorReference"),
        argument_instances=[
            _parse_automation_argument_instance(a)
            for a in data.get("argumentInstances", [])
        ],
        status=AutomationExecutionStatus(data["status"]),
        output=data.get("output"),
        domain_status=(
            AutomationExecutionDomainStatus(data["domainStatus"])
            if data.get("domainStatus")
            else None
        ),
        domain_status_message=data.get("domainStatusMessage"),
        created_at=_parse_datetime(data["createdAt"]),
        started_at=_parse_datetime(data.get("startedAt")),
        finished_at=_parse_datetime(data.get("finishedAt")),
        duration=data.get("duration"),
        workspace=None,
    )


def _parse_scheduled_execution_view(data: dict) -> ScheduledExecutionView:
    """Parse ScheduledExecutionView from GraphQL response."""
    return ScheduledExecutionView(
        name=data["name"],
        description=data["description"],
        cron=data["cron"],
        timezone=data["timezone"],
        automation_path=data["automationPath"],
        fire_time=_parse_datetime(data["fireTime"]),
        argument_instances=[
            _parse_automation_argument_instance(a)
            for a in data.get("argumentInstances", [])
        ],
        workspace=None,
    )


def _parse_error_code_view(data: dict) -> ErrorCodeView:
    """Parse ErrorCodeView from GraphQL response."""
    return ErrorCodeView(
        code=data["code"],
        message_template=data["messageTemplate"],
        parameters=data.get("parameters", []),
    )


class QueryOperations:
    """Query operations for Automation GraphQL API."""

    def __init__(self, execute_func: callable):
        """
        Initialize query operations.

        Args:
            execute_func: Function to execute GraphQL queries
        """
        self._execute = execute_func

    def get_automations(
        self,
        first: int | None = None,
        after: str | None = None,
        last: int | None = None,
        before: str | None = None,
        where: dict[str, Any] | None = None,
        order: list[dict[str, str]] | None = None,
    ) -> AutomationsConnection:
        """
        Retrieve a paginated, filterable, and sortable list of automations.

        Args:
            first: Returns the first n elements from the list
            after: Returns the elements in the list that come after the specified cursor
            last: Returns the last n elements from the list
            before: Returns the elements in the list that come before the specified cursor
            where: Filter conditions
            order: Sort order

        Returns:
            AutomationsConnection with automations
        """
        logger.debug(
            "Getting automations",
            first=first,
            after=after,
            last=last,
            before=before,
            where=where,
            order=order,
        )

        query = """
            query GetAutomations(
                $first: Int
                $after: String
                $last: Int
                $before: String
                $where: AutomationViewFilterInput
                $order: [AutomationViewSortInput!]
            ) {
                automations(
                    first: $first
                    after: $after
                    last: $last
                    before: $before
                    where: $where
                    order: $order
                ) {
                    pageInfo {
                        hasNextPage
                        hasPreviousPage
                        startCursor
                        endCursor
                    }
                    edges {
                        cursor
                        node {
                            workspaceName
                            path
                            description
                            environment
                            allowParallelExecution
                            argumentDefinitions {
                                name
                                description
                                mandatory
                            }
                        }
                    }
                    nodes {
                        workspaceName
                        path
                        description
                        environment
                        allowParallelExecution
                        argumentDefinitions {
                            name
                            description
                            mandatory
                        }
                    }
                    totalCount
                }
            }
        """

        variables = {
            "first": first,
            "after": after,
            "last": last,
            "before": before,
            "where": where,
            "order": order,
        }

        result = self._execute(query, variables)
        data = result["automations"]

        return AutomationsConnection(
            page_info=_parse_page_info(data["pageInfo"]),
            edges=[
                AutomationsEdge(
                    cursor=edge["cursor"],
                    node=_parse_automation_view(edge["node"]),
                )
                for edge in data["edges"]
            ],
            nodes=[_parse_automation_view(node) for node in data["nodes"]],
            total_count=data["totalCount"],
        )

    def get_executions(
        self,
        first: int | None = None,
        after: str | None = None,
        last: int | None = None,
        before: str | None = None,
        where: dict[str, Any] | None = None,
        order: list[dict[str, str]] | None = None,
    ) -> ExecutionsConnection:
        """
        Retrieve a paginated, filterable, and sortable list of automation executions.

        Args:
            first: Returns the first n elements from the list
            after: Returns the elements in the list that come after the specified cursor
            last: Returns the last n elements from the list
            before: Returns the elements in the list that come before the specified cursor
            where: Filter conditions
            order: Sort order

        Returns:
            ExecutionsConnection with executions
        """
        logger.debug(
            "Getting executions",
            first=first,
            after=after,
            last=last,
            before=before,
            where=where,
            order=order,
        )

        query = """
            query GetExecutions(
                $first: Int
                $after: String
                $last: Int
                $before: String
                $where: AutomationExecutionViewFilterInput
                $order: [AutomationExecutionViewSortInput!]
            ) {
                executions(
                    first: $first
                    after: $after
                    last: $last
                    before: $before
                    where: $where
                    order: $order
                ) {
                    pageInfo {
                        hasNextPage
                        hasPreviousPage
                        startCursor
                        endCursor
                    }
                    edges {
                        cursor
                        node {
                            id
                            branch
                            commit
                            workspaceName
                            repositoryName
                            repositoryUrl
                            automationPath
                            environment
                            initiatorType
                            initiatorReference
                            argumentInstances {
                                name
                                value
                            }
                            status
                            output
                            domainStatus
                            domainStatusMessage
                            createdAt
                            startedAt
                            finishedAt
                            duration
                        }
                    }
                    nodes {
                        id
                        branch
                        commit
                        workspaceName
                        repositoryName
                        repositoryUrl
                        automationPath
                        environment
                        initiatorType
                        initiatorReference
                        argumentInstances {
                            name
                            value
                        }
                        status
                        output
                        domainStatus
                        domainStatusMessage
                        createdAt
                        startedAt
                        finishedAt
                        duration
                    }
                    totalCount
                }
            }
        """

        variables = {
            "first": first,
            "after": after,
            "last": last,
            "before": before,
            "where": where,
            "order": order,
        }

        result = self._execute(query, variables)
        data = result["executions"]

        return ExecutionsConnection(
            page_info=_parse_page_info(data["pageInfo"]),
            edges=[
                ExecutionsEdge(
                    cursor=edge["cursor"],
                    node=_parse_automation_execution_view(edge["node"]),
                )
                for edge in data["edges"]
            ],
            nodes=[
                _parse_automation_execution_view(node) for node in data["nodes"]
            ],
            total_count=data["totalCount"],
        )

    def get_error_codes(
        self,
        first: int | None = None,
        after: str | None = None,
        last: int | None = None,
        before: str | None = None,
        where: dict[str, Any] | None = None,
        order: list[dict[str, str]] | None = None,
    ) -> ErrorCodesConnection:
        """
        Retrieve all available error codes in the automation system.

        Args:
            first: Returns the first n elements from the list
            after: Returns the elements in the list that come after the specified cursor
            last: Returns the last n elements from the list
            before: Returns the elements in the list that come before the specified cursor
            where: Filter conditions
            order: Sort order

        Returns:
            ErrorCodesConnection with error codes
        """
        logger.debug(
            "Getting error codes",
            first=first,
            after=after,
            last=last,
            before=before,
            where=where,
            order=order,
        )

        query = """
            query GetErrorCodes(
                $first: Int
                $after: String
                $last: Int
                $before: String
                $where: ErrorCodeViewFilterInput
                $order: [ErrorCodeViewSortInput!]
            ) {
                errorCodes(
                    first: $first
                    after: $after
                    last: $last
                    before: $before
                    where: $where
                    order: $order
                ) {
                    pageInfo {
                        hasNextPage
                        hasPreviousPage
                        startCursor
                        endCursor
                    }
                    edges {
                        cursor
                        node {
                            code
                            messageTemplate
                            parameters
                        }
                    }
                    nodes {
                        code
                        messageTemplate
                        parameters
                    }
                    totalCount
                }
            }
        """

        variables = {
            "first": first,
            "after": after,
            "last": last,
            "before": before,
            "where": where,
            "order": order,
        }

        result = self._execute(query, variables)
        data = result["errorCodes"]

        return ErrorCodesConnection(
            page_info=_parse_page_info(data["pageInfo"]),
            edges=[
                ErrorCodesEdge(
                    cursor=edge["cursor"],
                    node=_parse_error_code_view(edge["node"]),
                )
                for edge in data["edges"]
            ],
            nodes=[_parse_error_code_view(node) for node in data["nodes"]],
            total_count=data["totalCount"],
        )

    def get_repositories(
        self,
        first: int | None = None,
        after: str | None = None,
        last: int | None = None,
        before: str | None = None,
        where: dict[str, Any] | None = None,
        order: list[dict[str, str]] | None = None,
    ) -> RepositoriesConnection:
        """
        Retrieve a paginated, filterable, and sortable list of repositories.

        Args:
            first: Returns the first n elements from the list
            after: Returns the elements in the list that come after the specified cursor
            last: Returns the last n elements from the list
            before: Returns the elements in the list that come before the specified cursor
            where: Filter conditions
            order: Sort order

        Returns:
            RepositoriesConnection with repositories
        """
        logger.debug(
            "Getting repositories",
            first=first,
            after=after,
            last=last,
            before=before,
            where=where,
            order=order,
        )

        query = """
            query GetRepositories(
                $first: Int
                $after: String
                $last: Int
                $before: String
                $where: RepositoryViewFilterInput
                $order: [RepositoryViewSortInput!]
            ) {
                repositories(
                    first: $first
                    after: $after
                    last: $last
                    before: $before
                    where: $where
                    order: $order
                ) {
                    pageInfo {
                        hasNextPage
                        hasPreviousPage
                        startCursor
                        endCursor
                    }
                    edges {
                        cursor
                        node {
                            name
                            url
                            createdAt
                            changedAt
                            authenticationMethod
                            username
                            sshPublicKey
                        }
                    }
                    nodes {
                        name
                        url
                        createdAt
                        changedAt
                        authenticationMethod
                        username
                        sshPublicKey
                    }
                    totalCount
                }
            }
        """

        variables = {
            "first": first,
            "after": after,
            "last": last,
            "before": before,
            "where": where,
            "order": order,
        }

        result = self._execute(query, variables)
        data = result["repositories"]

        return RepositoriesConnection(
            page_info=_parse_page_info(data["pageInfo"]),
            edges=[
                RepositoriesEdge(
                    cursor=edge["cursor"],
                    node=_parse_repository_view(edge["node"]),
                )
                for edge in data["edges"]
            ],
            nodes=[_parse_repository_view(node) for node in data["nodes"]],
            total_count=data["totalCount"],
        )

    def get_schedules(
        self,
        first: int | None = None,
        after: str | None = None,
        last: int | None = None,
        before: str | None = None,
        where: dict[str, Any] | None = None,
        order: list[dict[str, str]] | None = None,
    ) -> SchedulesConnection:
        """
        Retrieve a paginated, filterable, and sortable list of schedules.

        Args:
            first: Returns the first n elements from the list
            after: Returns the elements in the list that come after the specified cursor
            last: Returns the last n elements from the list
            before: Returns the elements in the list that come before the specified cursor
            where: Filter conditions
            order: Sort order

        Returns:
            SchedulesConnection with schedules
        """
        logger.debug(
            "Getting schedules",
            first=first,
            after=after,
            last=last,
            before=before,
            where=where,
            order=order,
        )

        query = """
            query GetSchedules(
                $first: Int
                $after: String
                $last: Int
                $before: String
                $where: ScheduleViewFilterInput
                $order: [ScheduleViewSortInput!]
            ) {
                schedules(
                    first: $first
                    after: $after
                    last: $last
                    before: $before
                    where: $where
                    order: $order
                ) {
                    pageInfo {
                        hasNextPage
                        hasPreviousPage
                        startCursor
                        endCursor
                    }
                    edges {
                        cursor
                        node {
                            automationPath
                            name
                            description
                            cron
                            timezone
                            active
                            argumentInstances {
                                name
                                value
                            }
                            version
                        }
                    }
                    nodes {
                        automationPath
                        name
                        description
                        cron
                        timezone
                        active
                        argumentInstances {
                            name
                            value
                        }
                        version
                    }
                    totalCount
                }
            }
        """

        variables = {
            "first": first,
            "after": after,
            "last": last,
            "before": before,
            "where": where,
            "order": order,
        }

        result = self._execute(query, variables)
        data = result["schedules"]

        return SchedulesConnection(
            page_info=_parse_page_info(data["pageInfo"]),
            edges=[
                SchedulesEdge(
                    cursor=edge["cursor"],
                    node=_parse_schedule_view(edge["node"]),
                )
                for edge in data["edges"]
            ],
            nodes=[_parse_schedule_view(node) for node in data["nodes"]],
            total_count=data["totalCount"],
        )

    def get_scheduled_executions(
        self,
        from_time: datetime | None = None,
        to_time: datetime | None = None,
        first: int | None = None,
        after: str | None = None,
        last: int | None = None,
        before: str | None = None,
    ) -> ScheduledExecutionsConnection:
        """
        Retrieve a paginated list of scheduled executions within a specified time range.

        Args:
            from_time: Start time for scheduled executions (defaults to current time if not specified)
            to_time: End time for scheduled executions (optional)
            first: Returns the first n elements from the list
            after: Returns the elements in the list that come after the specified cursor
            last: Returns the last n elements from the list
            before: Returns the elements in the list that come before the specified cursor

        Returns:
            ScheduledExecutionsConnection with scheduled executions
        """
        logger.debug(
            "Getting scheduled executions",
            from_time=from_time,
            to_time=to_time,
            first=first,
            after=after,
            last=last,
            before=before,
        )

        query = """
            query GetScheduledExecutions(
                $from: DateTime
                $to: DateTime
                $first: Int
                $after: String
                $last: Int
                $before: String
            ) {
                scheduledExecutions(
                    from: $from
                    to: $to
                    first: $first
                    after: $after
                    last: $last
                    before: $before
                ) {
                    pageInfo {
                        hasNextPage
                        hasPreviousPage
                        startCursor
                        endCursor
                    }
                    edges {
                        cursor
                        node {
                            name
                            description
                            cron
                            timezone
                            automationPath
                            fireTime
                            argumentInstances {
                                name
                                value
                            }
                        }
                    }
                    nodes {
                        name
                        description
                        cron
                        timezone
                        automationPath
                        fireTime
                        argumentInstances {
                            name
                            value
                        }
                    }
                }
            }
        """

        variables = {
            "from": from_time.isoformat() if from_time else None,
            "to": to_time.isoformat() if to_time else None,
            "first": first,
            "after": after,
            "last": last,
            "before": before,
        }

        result = self._execute(query, variables)
        data = result["scheduledExecutions"]

        return ScheduledExecutionsConnection(
            page_info=_parse_page_info(data["pageInfo"]),
            edges=[
                ScheduledExecutionsEdge(
                    cursor=edge["cursor"],
                    node=_parse_scheduled_execution_view(edge["node"]),
                )
                for edge in data["edges"]
            ],
            nodes=[
                _parse_scheduled_execution_view(node) for node in data["nodes"]
            ],
        )

    def get_workspaces(
        self,
        first: int | None = None,
        after: str | None = None,
        last: int | None = None,
        before: str | None = None,
        where: dict[str, Any] | None = None,
        order: list[dict[str, str]] | None = None,
    ) -> WorkspacesConnection:
        """
        Retrieve a paginated, filterable, and sortable list of workspaces.

        Args:
            first: Returns the first n elements from the list
            after: Returns the elements in the list that come after the specified cursor
            last: Returns the last n elements from the list
            before: Returns the elements in the list that come before the specified cursor
            where: Filter conditions
            order: Sort order

        Returns:
            WorkspacesConnection with workspaces
        """
        logger.debug(
            "Getting workspaces",
            first=first,
            after=after,
            last=last,
            before=before,
            where=where,
            order=order,
        )

        query = """
            query GetWorkspaces(
                $first: Int
                $after: String
                $last: Int
                $before: String
                $where: WorkspaceViewFilterInput
                $order: [WorkspaceViewSortInput!]
            ) {
                workspaces(
                    first: $first
                    after: $after
                    last: $last
                    before: $before
                    where: $where
                    order: $order
                ) {
                    pageInfo {
                        hasNextPage
                        hasPreviousPage
                        startCursor
                        endCursor
                    }
                    edges {
                        cursor
                        node {
                            name
                            repositoryName
                            buildStatus
                            buildErrors {
                                code
                                messageTemplate
                                data {
                                    key
                                    value
                                }
                            }
                            buildBranch
                            buildCommit
                            buildStartedAt
                            buildFinishedAt
                            buildDuration
                            activeBranch
                            activeCommit
                            createdAt
                            changedAt
                        }
                    }
                    nodes {
                        name
                        repositoryName
                        buildStatus
                        buildErrors {
                            code
                            messageTemplate
                            data {
                                key
                                value
                            }
                        }
                        buildBranch
                        buildCommit
                        buildStartedAt
                        buildFinishedAt
                        buildDuration
                        activeBranch
                        activeCommit
                        createdAt
                        changedAt
                    }
                    totalCount
                }
            }
        """

        variables = {
            "first": first,
            "after": after,
            "last": last,
            "before": before,
            "where": where,
            "order": order,
        }

        result = self._execute(query, variables)
        data = result["workspaces"]

        return WorkspacesConnection(
            page_info=_parse_page_info(data["pageInfo"]),
            edges=[
                WorkspacesEdge(
                    cursor=edge["cursor"],
                    node=_parse_workspace_view(edge["node"]),
                )
                for edge in data["edges"]
            ],
            nodes=[_parse_workspace_view(node) for node in data["nodes"]],
            total_count=data["totalCount"],
        )

    def get_service_info(self) -> ServiceInfo:
        """
        Retrieve information about the automation service.

        Returns:
            ServiceInfo with service details
        """
        logger.debug("Getting service info")

        query = """
            query GetServiceInfo {
                automationServiceInfo {
                    name
                    version
                    informationalVersion
                }
            }
        """

        result = self._execute(query)
        data = result["automationServiceInfo"]

        return ServiceInfo(
            name=data["name"],
            version=data["version"],
            informational_version=data["informationalVersion"],
        )


class MutationOperations:
    """Mutation operations for Automation GraphQL API."""

    def __init__(self, execute_func: callable):
        """
        Initialize mutation operations.

        Args:
            execute_func: Function to execute GraphQL mutations
        """
        self._execute = execute_func

    def execute_automation(
        self,
        workspace_name: str,
        automation_path: str,
        initiator_type: ExecutionInitiator,
        arguments: list[dict[str, str]] | None = None,
        initiator_reference: str | None = None,
    ) -> ExecutePayload:
        """
        Execute an automation in a specified workspace with the provided arguments.

        Args:
            workspace_name: Name of the workspace containing the automation
            automation_path: Path to the automation script
            initiator_type: Type of initiator (Manual, Script, or Schedule)
            arguments: Arguments to pass to the automation
            initiator_reference: Optional reference to the initiator

        Returns:
            ExecutePayload with execution ID
        """
        logger.info(
            "Executing automation",
            workspace_name=workspace_name,
            automation_path=automation_path,
            initiator_type=initiator_type,
        )

        mutation = """
            mutation ExecuteAutomation($input: ExecuteInput!) {
                execute(input: $input) {
                    id
                }
            }
        """

        variables = {
            "input": {
                "workspaceName": workspace_name,
                "automationPath": automation_path,
                "initiatorType": initiator_type.value,
                "arguments": arguments or [],
                "initiatorReference": initiator_reference,
            }
        }

        result = self._execute(mutation, variables)
        data = result["execute"]

        return ExecutePayload(id=UUID(data["id"]))

    def create_repository(
        self,
        name: str,
        url: str,
        credentials_method: RepositoryAuthenticationMethod,
        username: str | None = None,
        password: str | None = None,
    ) -> CreateRepositoryPayload:
        """
        Create a new repository with the specified name and remote configuration.

        Args:
            name: Repository name
            url: URL of the remote repository
            credentials_method: Authentication method (UsernamePassword or SshKey)
            username: Username for authentication (optional)
            password: Password or token for authentication (optional)

        Returns:
            CreateRepositoryPayload with repository name
        """
        logger.info("Creating repository", name=name, url=url)

        mutation = """
            mutation CreateRepository($input: CreateRepositoryInput!) {
                createRepository(input: $input) {
                    name
                }
            }
        """

        variables = {
            "input": {
                "name": name,
                "remote": {
                    "url": url,
                    "credentials": {
                        "method": credentials_method.value,
                        "username": username,
                        "password": password,
                    },
                },
            }
        }

        result = self._execute(mutation, variables)
        data = result["createRepository"]

        return CreateRepositoryPayload(name=data["name"])

    def update_repository(
        self,
        name: str,
        new_name: str | None = None,
        url: str | None = None,
        credentials_method: RepositoryAuthenticationMethod | None = None,
        username: str | None = None,
        password: str | None = None,
    ) -> UpdateRepositoryPayload:
        """
        Update an existing repository's name or remote configuration.

        Args:
            name: Current repository name
            new_name: New repository name (optional)
            url: New URL of the remote repository (optional)
            credentials_method: New authentication method (optional)
            username: New username for authentication (optional)
            password: New password or token for authentication (optional)

        Returns:
            UpdateRepositoryPayload with repository name
        """
        logger.info("Updating repository", name=name, new_name=new_name)

        mutation = """
            mutation UpdateRepository($input: UpdateRepositoryInput!) {
                updateRepository(input: $input) {
                    name
                }
            }
        """

        remote = None
        if url or credentials_method:
            remote = {
                "url": url,
                "credentials": {
                    "method": credentials_method.value if credentials_method else None,
                    "username": username,
                    "password": password,
                },
            }

        variables = {
            "input": {
                "name": name,
                "newName": new_name,
                "remote": remote,
            }
        }

        result = self._execute(mutation, variables)
        data = result["updateRepository"]

        return UpdateRepositoryPayload(name=data["name"])

    def delete_repository(self, name: str) -> DeleteRepositoryPayload:
        """
        Delete a repository by name.

        Args:
            name: Repository name

        Returns:
            DeleteRepositoryPayload with repository name
        """
        logger.info("Deleting repository", name=name)

        mutation = """
            mutation DeleteRepository($input: DeleteRepositoryInput!) {
                deleteRepository(input: $input) {
                    name
                }
            }
        """

        variables = {"input": {"name": name}}

        result = self._execute(mutation, variables)
        data = result["deleteRepository"]

        return DeleteRepositoryPayload(name=data["name"])

    def renew_repository_ssh_key(self, name: str) -> RenewRepositorySshKeyPayload:
        """
        Renew the SSH key for a repository.

        Args:
            name: Repository name

        Returns:
            RenewRepositorySshKeyPayload with repository name
        """
        logger.info("Renewing repository SSH key", name=name)

        mutation = """
            mutation RenewRepositorySshKey($input: RenewRepositorySshKeyInput!) {
                renewRepositorySshKey(input: $input) {
                    name
                }
            }
        """

        variables = {"input": {"name": name}}

        result = self._execute(mutation, variables)
        data = result["renewRepositorySshKey"]

        return RenewRepositorySshKeyPayload(name=data["name"])

    def create_schedule(
        self,
        workspace_name: str,
        automation_path: str,
        name: str,
        description: str,
        cron: str,
        timezone: str,
        active: bool,
        arguments: list[dict[str, str]] | None = None,
    ) -> CreateSchedulePayload:
        """
        Create a new schedule for automated execution of an automation.

        Args:
            workspace_name: Name of the workspace containing the automation
            automation_path: Path to the automation script
            name: Name of the schedule
            description: Description of the schedule
            cron: Cron expression defining the schedule
            timezone: Timezone for the schedule
            active: Whether the schedule is active
            arguments: Arguments to pass to the automation

        Returns:
            CreateSchedulePayload with schedule details
        """
        logger.info(
            "Creating schedule",
            workspace_name=workspace_name,
            automation_path=automation_path,
            name=name,
        )

        mutation = """
            mutation CreateSchedule($input: CreateScheduleInput!) {
                createSchedule(input: $input) {
                    name
                    workspaceName
                    automationPath
                }
            }
        """

        variables = {
            "input": {
                "workspaceName": workspace_name,
                "automationPath": automation_path,
                "name": name,
                "description": description,
                "cron": cron,
                "timezone": timezone,
                "active": active,
                "arguments": arguments or [],
            }
        }

        result = self._execute(mutation, variables)
        data = result["createSchedule"]

        return CreateSchedulePayload(
            name=data["name"],
            workspace_name=data["workspaceName"],
            automation_path=data["automationPath"],
        )

    def update_schedule(
        self,
        workspace_name: str,
        automation_path: str,
        name: str,
        new_name: str | None = None,
        description: str | None = None,
        cron: str | None = None,
        timezone: str | None = None,
        active: bool | None = None,
        arguments: list[dict[str, str]] | None = None,
    ) -> UpdateSchedulePayload:
        """
        Update an existing schedule's configuration.

        Args:
            workspace_name: Name of the workspace containing the automation
            automation_path: Path to the automation script
            name: Current name of the schedule
            new_name: New name of the schedule (optional)
            description: New description of the schedule (optional)
            cron: New cron expression (optional)
            timezone: New timezone (optional)
            active: New active state (optional)
            arguments: New arguments (optional)

        Returns:
            UpdateSchedulePayload with schedule details
        """
        logger.info(
            "Updating schedule",
            workspace_name=workspace_name,
            automation_path=automation_path,
            name=name,
        )

        mutation = """
            mutation UpdateSchedule($input: UpdateScheduleInput!) {
                updateSchedule(input: $input) {
                    name
                    workspaceName
                    automationPath
                }
            }
        """

        variables = {
            "input": {
                "workspaceName": workspace_name,
                "automationPath": automation_path,
                "name": name,
                "newName": new_name,
                "description": description,
                "cron": cron,
                "timezone": timezone,
                "active": active,
                "arguments": arguments,
            }
        }

        result = self._execute(mutation, variables)
        data = result["updateSchedule"]

        return UpdateSchedulePayload(
            name=data["name"],
            workspace_name=data["workspaceName"],
            automation_path=data["automationPath"],
        )

    def delete_schedule(
        self, workspace_name: str, automation_path: str, name: str
    ) -> DeleteSchedulePayload:
        """
        Delete a schedule.

        Args:
            workspace_name: Name of the workspace containing the automation
            automation_path: Path to the automation script
            name: Name of the schedule

        Returns:
            DeleteSchedulePayload with schedule details
        """
        logger.info(
            "Deleting schedule",
            workspace_name=workspace_name,
            automation_path=automation_path,
            name=name,
        )

        mutation = """
            mutation DeleteSchedule($input: DeleteScheduleInput!) {
                deleteSchedule(input: $input) {
                    name
                    workspaceName
                    automationPath
                }
            }
        """

        variables = {
            "input": {
                "workspaceName": workspace_name,
                "automationPath": automation_path,
                "name": name,
            }
        }

        result = self._execute(mutation, variables)
        data = result["deleteSchedule"]

        return DeleteSchedulePayload(
            name=data["name"],
            workspace_name=data["workspaceName"],
            automation_path=data["automationPath"],
        )

    def create_workspace(
        self, repository_name: str, name: str, branch_name: str, commit: str
    ) -> CreateWorkspacePayload:
        """
        Create a new workspace in a repository with the specified branch.

        Args:
            repository_name: Repository name
            name: Workspace name
            branch_name: Name of the branch
            commit: Commit hash to checkout

        Returns:
            CreateWorkspacePayload with workspace name
        """
        logger.info(
            "Creating workspace",
            repository_name=repository_name,
            name=name,
            branch_name=branch_name,
        )

        mutation = """
            mutation CreateWorkspace($input: CreateWorkspaceInput!) {
                createWorkspace(input: $input) {
                    name
                }
            }
        """

        variables = {
            "input": {
                "repositoryName": repository_name,
                "name": name,
                "branch": {"name": branch_name, "commit": commit},
            }
        }

        result = self._execute(mutation, variables)
        data = result["createWorkspace"]

        return CreateWorkspacePayload(name=data["name"])

    def update_workspace(
        self,
        name: str,
        new_name: str | None = None,
        branch_name: str | None = None,
        commit: str | None = None,
    ) -> UpdateWorkspacePayload:
        """
        Update an existing workspace's name or branch configuration.

        Args:
            name: Current workspace name
            new_name: New workspace name (optional)
            branch_name: New branch name (optional)
            commit: New commit hash to checkout (optional)

        Returns:
            UpdateWorkspacePayload with workspace name
        """
        logger.info("Updating workspace", name=name, new_name=new_name)

        mutation = """
            mutation UpdateWorkspace($input: UpdateWorkspaceInput!) {
                updateWorkspace(input: $input) {
                    name
                }
            }
        """

        branch = None
        if branch_name and commit:
            branch = {"name": branch_name, "commit": commit}

        variables = {
            "input": {
                "name": name,
                "newName": new_name,
                "branch": branch,
            }
        }

        result = self._execute(mutation, variables)
        data = result["updateWorkspace"]

        return UpdateWorkspacePayload(name=data["name"])

    def delete_workspace(self, name: str) -> DeleteWorkspacePayload:
        """
        Delete a workspace by name.

        Args:
            name: Workspace name

        Returns:
            DeleteWorkspacePayload with workspace name
        """
        logger.info("Deleting workspace", name=name)

        mutation = """
            mutation DeleteWorkspace($input: DeleteWorkspaceInput!) {
                deleteWorkspace(input: $input) {
                    name
                }
            }
        """

        variables = {"input": {"name": name}}

        result = self._execute(mutation, variables)
        data = result["deleteWorkspace"]

        return DeleteWorkspacePayload(name=data["name"])

    def synchronize_workspace(self, name: str) -> SynchronizeWorkspacePayload:
        """
        Synchronize a workspace with its remote repository.

        Args:
            name: Workspace name

        Returns:
            SynchronizeWorkspacePayload with workspace name
        """
        logger.info("Synchronizing workspace", name=name)

        mutation = """
            mutation SynchronizeWorkspace($input: SynchronizeWorkspaceInput!) {
                synchronizeWorkspace(input: $input) {
                    name
                }
            }
        """

        variables = {"input": {"name": name}}

        result = self._execute(mutation, variables)
        data = result["synchronizeWorkspace"]

        return SynchronizeWorkspacePayload(name=data["name"])
