"""Container infrastructure resource handlers for CleverAgents.

Implements the five handler classes referenced in
``_resource_registry_container.py`` for the seven built-in container
infrastructure resource types:

- ``ContainerRuntimeHandler`` -- for ``container-runtime``
- ``ContainerImageHandler``   -- for ``container-image``
- ``ContainerChildHandler``   -- for ``container-mount``, ``container-exec-env``,
  ``container-port`` (shared child handler)
- ``ContainerVolumeHandler``  -- for ``container-volume``
- ``ContainerNetworkHandler`` -- for ``container-network``

All handlers extend BaseResourceHandler and satisfy the ResourceHandler protocol.

Container resources use ``sandbox_strategy = "none"`` (or ``"snapshot"``
for child/volume types) because the container runtime itself provides
isolation.  Actual container SDK operations are NOT implemented --
calling :meth:`resolve` raises :exc:`NotImplementedError` after basic
validation.  This mirrors the pattern used by CloudResourceHandler.

Based on:
    - src/cleveragents/application/services/_resource_registry_container.py
    - docs/specification.md ~line 25096-25114 (container handler table)
    - ADR-039: Container Resource Types
    - Issue #2907: Container infrastructure resource types missing handler module
"""

from __future__ import annotations

import hashlib
import logging
from typing import Any

from cleveragents.domain.models.core.resource import Resource, SandboxStrategy
from cleveragents.infrastructure.sandbox.manager import SandboxManager
from cleveragents.resource.handlers._base import EMPTY_CONTENT_HASH, BaseResourceHandler
from cleveragents.resource.handlers.protocol import (
    Content,
    DeleteResult,
    DiffResult,
    WriteResult,
)
from cleveragents.tool.context import BoundResource

logger = logging.getLogger(__name__)

__all__ = [
    "ContainerChildHandler",
    "ContainerImageHandler",
    "ContainerNetworkHandler",
    "ContainerRuntimeHandler",
    "ContainerVolumeHandler",
]


# ---------------------------------------------------------------------------
# Shared helpers
# ---------------------------------------------------------------------------


def _identity_hash(resource: Resource, algorithm: str = "sha256") -> str:
    """Compute an identity hash for a container resource.

    The hash is based on the resource type name and location (e.g. socket
    path, image reference, volume name, network name).  Returns
    :data:`EMPTY_CONTENT_HASH` if no location is set.

    Args:
        resource: The container resource.
        algorithm: Hash algorithm name (default ``sha256``).

    Returns:
        Hex-encoded hash digest, or :data:`EMPTY_CONTENT_HASH`.
    """
    if not resource.location:
        return EMPTY_CONTENT_HASH
    h = hashlib.new(algorithm)
    h.update(resource.resource_type_name.encode("utf-8"))
    h.update(b"\0")
    h.update(resource.location.encode("utf-8"))
    return h.hexdigest()


# ---------------------------------------------------------------------------
# Shared base for all container handlers
# ---------------------------------------------------------------------------


class _ContainerBaseHandler(BaseResourceHandler):
    """Shared base for all container infrastructure handlers.

    Provides:
    - ``resolve`` -- raises NotImplementedError (container sandbox
      provisioning is not yet implemented).
    - ``content_hash`` -- identity hash based on resource type + location.
    - All CRUD and lifecycle stubs -- raise NotImplementedError.

    Subclasses set ``_default_strategy`` and ``_type_label``.
    """

    def resolve(
        self,
        *,
        resource: Resource,
        plan_id: str,
        slot_name: str,
        sandbox_manager: SandboxManager,
        access: str = "read_only",
    ) -> BoundResource:
        """Raise -- container sandbox provisioning is not yet implemented.

        Args:
            resource: A container resource instance.
            plan_id: The plan requesting the sandbox.
            slot_name: Name of the tool resource slot being filled.
            sandbox_manager: The sandbox lifecycle manager (unused).
            access: Access mode (unused).

        Raises:
            NotImplementedError: Always.
        """
        raise NotImplementedError(
            f"Container resource sandbox provisioning is not yet implemented. "
            f"Resource '{resource.resource_id}' "
            f"(type={resource.resource_type_name}, "
            f"plan={plan_id}, slot={slot_name})."
        )

    # -- CRUD stubs --------------------------------------------------------

    def read(self, *, resource: Resource, path: str = "") -> Content:
        """Not supported for container resources."""
        raise NotImplementedError(f"{self._type_label} handler does not support read()")

    def write(self, *, resource: Resource, path: str, data: bytes) -> WriteResult:
        """Not supported for container resources."""
        raise NotImplementedError(
            f"{self._type_label} handler does not support write()"
        )

    def delete(self, *, resource: Resource, path: str = "") -> DeleteResult:
        """Not supported for container resources."""
        raise NotImplementedError(
            f"{self._type_label} handler does not support delete()"
        )

    def list_children(self, *, resource: Resource) -> list[str]:
        """Not supported for container resources."""
        raise NotImplementedError(
            f"{self._type_label} handler does not support list_children()"
        )

    def diff(self, *, resource: Resource, other_location: str) -> DiffResult:
        """Not supported for container resources."""
        raise NotImplementedError(f"{self._type_label} handler does not support diff()")

    def discover_children(self, *, resource: Resource) -> list[Resource]:
        """Not supported for container resources."""
        raise NotImplementedError(
            f"{self._type_label} handler does not support discover_children()"
        )

    # -- Lifecycle stubs ---------------------------------------------------

    def create_sandbox(
        self,
        *,
        resource: Resource,
        plan_id: str,
        sandbox_manager: SandboxManager,
    ) -> Any:
        """Not supported for container resources."""
        raise NotImplementedError(
            f"{self._type_label} handler does not support create_sandbox()"
        )

    def create_checkpoint(
        self,
        *,
        resource: Resource,
        plan_id: str,
        sandbox_manager: SandboxManager,
        phase: str = "execution",
    ) -> Any:
        """Not supported for container resources."""
        raise NotImplementedError(
            f"{self._type_label} handler does not support create_checkpoint()"
        )

    def rollback_to(
        self,
        *,
        resource: Resource,
        plan_id: str,
        checkpoint_id: str,
        sandbox_manager: SandboxManager,
    ) -> Any:
        """Not supported for container resources."""
        raise NotImplementedError(
            f"{self._type_label} handler does not support rollback_to()"
        )

    def project_access(
        self,
        *,
        resource: Resource,
        principal: str,
        action: str = "read",
        project_id: str = "",
    ) -> Any:
        """Not supported for container resources."""
        raise NotImplementedError(
            f"{self._type_label} handler does not support project_access()"
        )

    # -- Content hashing ---------------------------------------------------

    def content_hash(
        self,
        resource: Resource,
        *,
        algorithm: str = "sha256",
    ) -> str:
        """Compute an identity hash for a container resource.

        The hash is based on the resource type name and location.
        Returns :data:`EMPTY_CONTENT_HASH` if no location is set.

        Args:
            resource: The container resource.
            algorithm: Hash algorithm name (default ``sha256``).

        Returns:
            Hex-encoded hash digest, or :data:`EMPTY_CONTENT_HASH`.
        """
        return _identity_hash(resource, algorithm)


# ---------------------------------------------------------------------------
# Concrete handler classes
# ---------------------------------------------------------------------------


class ContainerRuntimeHandler(_ContainerBaseHandler):
    """Handler for ``container-runtime`` resource types.

    A container runtime resource represents a container engine
    (Docker, Podman, containerd, etc.) identified by its socket path
    or remote endpoint URL.

    Sandbox provisioning is NOT implemented -- calling :meth:`resolve`
    raises :exc:`NotImplementedError`.

    This handler satisfies the ResourceHandler protocol.
    """

    _default_strategy = SandboxStrategy.NONE
    _type_label = "container-runtime"


class ContainerImageHandler(_ContainerBaseHandler):
    """Handler for ``container-image`` resource types.

    A container image resource represents an immutable container image
    identified by tag and/or digest (e.g. ``ubuntu:22.04``,
    ``ghcr.io/org/app@sha256:...``).

    Sandbox provisioning is NOT implemented -- calling :meth:`resolve`
    raises :exc:`NotImplementedError`.

    This handler satisfies the ResourceHandler protocol.
    """

    _default_strategy = SandboxStrategy.NONE
    _type_label = "container-image"


class ContainerChildHandler(_ContainerBaseHandler):
    """Shared handler for container child resource types.

    Used by three resource types that represent child components of a
    running container instance:

    - ``container-mount`` -- bind mount or volume mount inside a container
    - ``container-exec-env`` -- execution environment variables and config
    - ``container-port`` -- port mapping between host and container

    These resources are not user-addable (``user_addable = False``) and
    are discovered automatically from a running container instance.

    Sandbox provisioning is NOT implemented -- calling :meth:`resolve`
    raises :exc:`NotImplementedError`.

    This handler satisfies the ResourceHandler protocol.
    """

    _default_strategy = SandboxStrategy.SNAPSHOT
    _type_label = "container-child"


class ContainerVolumeHandler(_ContainerBaseHandler):
    """Handler for ``container-volume`` resource types.

    A container volume resource represents a named container volume
    managed by the runtime engine (Docker, Podman, etc.).

    Sandbox provisioning is NOT implemented -- calling :meth:`resolve`
    raises :exc:`NotImplementedError`.

    This handler satisfies the ResourceHandler protocol.
    """

    _default_strategy = SandboxStrategy.SNAPSHOT
    _type_label = "container-volume"


class ContainerNetworkHandler(_ContainerBaseHandler):
    """Handler for ``container-network`` resource types.

    A container network resource represents a container network
    (bridge, host, overlay, macvlan, or none).

    Sandbox provisioning is NOT implemented -- calling :meth:`resolve`
    raises :exc:`NotImplementedError`.

    This handler satisfies the ResourceHandler protocol.
    """

    _default_strategy = SandboxStrategy.NONE
    _type_label = "container-network"
