"""BlackAnt Docker Client module.

High-level Docker client providing user-friendly API for Docker operations
through BlackAnt platform with automatic authentication.
"""

import os
import json
from typing import Dict, Any, Optional, List

from ..auth.blackant_auth import BlackAntAuth
from ..auth.role_assignment import get_role_assignment_manager
from ..http.client import HTTPClient, HTTPConnectionError
from ..exceptions import BlackAntDockerError
from ..utils.logging import get_logger
from .builder import DockerImageBuilder


class BlackAntDockerClient:
    """Docker client with BlackAnt authentication integration.

    Provides high-level Docker operations through BlackAnt's HTTP API
    with automatic Bearer token authentication. All requests are routed
    through Nginx proxy which validates tokens with Keycloak.

    This client uses the existing HTTPClient with persistent sessions,
    connection pooling, and request ID tracking for efficient and
    traceable API communication.

    Args:
        auth (BlackAntAuth): Authentication object with credentials.
        base_url (str, optional): Base URL for BlackAnt API.

    Examples:
        >>> auth = BlackAntAuth(user="my_name", password="xxx")
        >>> client = BlackAntDockerClient(auth=auth)
        >>> print(client.version)  # "18.9.3"
        >>> containers = client.containers()
    """

    def \
            __init__(self, auth: BlackAntAuth, base_url: Optional[str] = None):
        """Initialize Docker client with authentication.

        Args:
            auth: BlackAntAuth object with user credentials.
            base_url: Optional base URL, defaults to environment variable.
        """
        self.auth = auth
        self.base_url = base_url or os.getenv(
            "BLACKANT_BASE_URL",
            "https://dev.blackant.app"
        )

        # Initialize HTTPClient with persistent session and connection pooling
        self.http_client = HTTPClient(
            base_url=self.base_url,
            auth_token_store=auth.token_store  # Share token store with auth
        )

        self.logger = get_logger("docker.client")

        # Initialize Docker image builder with auth for remote daemon
        self.image_builder = DockerImageBuilder(auth=self.auth)

        # Ensure authentication on initialization
        self.auth.get_token()
        self.logger.info("BlackAntDockerClient initialized")

    @property
    def version(self) -> str:
        """Get Docker daemon version.

        Returns the Docker daemon version string through BlackAnt API.
        This provides the Docker daemon version information through BlackAnt API.

        Returns:
            str: Docker version string (e.g., "18.9.3").

        Raises:
            BlackAntDockerError: If version fetch fails.
        """
        try:
            response = self.http_client.send_request(
                endpoint="/api/docker/version",
                method="GET"
            )
            response.raise_for_status()

            data = response.json()
            version = data.get("version", data.get("Version", "unknown"))

            self.logger.debug(f"Docker version: {version}")
            return version

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to fetch Docker version: {error}")
            raise BlackAntDockerError(f"Could not fetch Docker version: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error fetching version: {error}")
            raise BlackAntDockerError(f"Version fetch failed: {error}") from error

    def containers(self, all_containers: bool = False) -> List[Dict[str, Any]]:
        """List Docker containers.

        Args:
            all_containers: If True, show all containers. If False, only running.

        Returns:
            List of container dictionaries with details.

        Raises:
            BlackAntDockerError: If container list fails.
        """
        try:
            params = {"all": str(all_containers).lower()} if all_containers else {}

            response = self.http_client.send_request(
                endpoint="/api/docker/v1.24/containers/json",
                method="GET",
                json=params if params else None
            )
            response.raise_for_status()

            containers = response.json()
            self.logger.debug(f"Found {len(containers)} containers")
            return containers

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to list containers: {error}")
            raise BlackAntDockerError(f"Could not list containers: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error listing containers: {error}")
            raise BlackAntDockerError(f"Container list failed: {error}") from error

    def images(self) -> List[Dict[str, Any]]:
        """List Docker images.

        Returns:
            List of image dictionaries with details.

        Raises:
            BlackAntDockerError: If image list fails.
        """
        try:
            response = self.http_client.send_request(
                endpoint="/api/docker/v1.24/images/json",
                method="GET"
            )
            response.raise_for_status()

            images = response.json()
            self.logger.debug(f"Found {len(images)} images")
            return images

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to list images: {error}")
            raise BlackAntDockerError(f"Could not list images: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error listing images: {error}")
            raise BlackAntDockerError(f"Image list failed: {error}") from error

    def services(self) -> List[Dict[str, Any]]:
        """List Docker services (Swarm mode).

        Returns:
            List of service dictionaries with details.

        Raises:
            BlackAntDockerError: If service list fails.
        """
        try:
            response = self.http_client.send_request(
                endpoint="/api/docker/services",
                method="GET"
            )
            response.raise_for_status()

            services = response.json()
            self.logger.debug(f"Found {len(services)} services")
            return services

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to list services: {error}")
            raise BlackAntDockerError(f"Could not list services: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error listing services: {error}")
            raise BlackAntDockerError(f"Service list failed: {error}") from error

    def info(self) -> Dict[str, Any]:
        """Get Docker daemon system information.

        Returns:
            Dictionary with Docker daemon info.

        Raises:
            BlackAntDockerError: If info fetch fails.
        """
        try:
            response = self.http_client.send_request(
                endpoint="/api/docker/info",
                method="GET"
            )
            response.raise_for_status()

            info = response.json()
            self.logger.debug("Fetched Docker daemon info")
            return info

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to fetch Docker info: {error}")
            raise BlackAntDockerError(f"Could not fetch Docker info: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error fetching info: {error}")
            raise BlackAntDockerError(f"Info fetch failed: {error}") from error

    def ping(self) -> bool:
        """Ping Docker daemon to check connectivity.

        Returns:
            bool: True if Docker daemon is accessible.
        """
        try:
            response = self.http_client.send_request(
                endpoint="/api/docker/v1.24/_ping",
                method="GET"
            )
            return response.status_code == 200

        except (ConnectionError, TimeoutError, ValueError):
            return False

    def build_image(self, dockerfile_path: str, tag: str, context_path: str = ".",
                   build_args: Optional[Dict[str, str]] = None,
                   stream_logs: bool = True) -> Dict[str, Any]:
        """Build Docker image from Dockerfile with streaming logs.

        Args:
            dockerfile_path: Path to Dockerfile relative to context.
            tag: Image tag (e.g., "myapp:latest").
            context_path: Build context directory path.
            build_args: Build arguments dict.
            stream_logs: Whether to stream build logs.

        Returns:
            Build result with logs and image ID.

        Raises:
            BlackAntDockerError: If build fails.
        """
        try:
            import tarfile
            import io
            import base64

            # Create tar archive from context
            tar_buffer = io.BytesIO()
            with tarfile.open(fileobj=tar_buffer, mode='w:gz') as tar:
                tar.add(context_path, arcname='.')

            tar_data = base64.b64encode(tar_buffer.getvalue()).decode()

            build_data = {
                "dockerfile": dockerfile_path,
                "t": tag,
                "buildargs": build_args or {},
                "context": tar_data
            }

            response = self.http_client.send_request(
                endpoint="/api/docker/v1.24/build",
                method="POST",
                json=build_data,
                req_timeout=300.0
            )
            response.raise_for_status()

            result = {"logs": [], "image_id": None, "success": False}

            if stream_logs:
                # Parse streaming response
                for line in response.iter_lines():
                    if line:
                        try:
                            log_entry = line.decode().strip()
                            result["logs"].append(log_entry)
                            self.logger.info(f"Build: {log_entry}")
                        except Exception:
                            pass

            build_response = response.json() if hasattr(response, 'json') else {}
            result["image_id"] = build_response.get("Id", tag)
            result["success"] = True

            self.logger.info(f"Image built successfully: {tag}")
            return result

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to build image: {error}")
            raise BlackAntDockerError(f"Could not build image: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error building image: {error}")
            raise BlackAntDockerError(f"Image build failed: {error}") from error

    def create_container(self, image: str, name: Optional[str] = None,
                        command: Optional[List[str]] = None,
                        environment: Optional[Dict[str, str]] = None,
                        ports: Optional[Dict[str, int]] = None,
                        volumes: Optional[Dict[str, str]] = None) -> str:
        """Create a new container.

        Args:
            image: Docker image name/tag.
            name: Container name (optional).
            command: Command to run in container.
            environment: Environment variables.
            ports: Port mappings {container_port: host_port}.
            volumes: Volume mappings {host_path: container_path}.

        Returns:
            Container ID.

        Raises:
            BlackAntDockerError: If container creation fails.
        """
        try:
            create_data = {
                "Image": image,
                "Cmd": command or [],
                "Env": [f"{k}={v}" for k, v in (environment or {}).items()],
                "ExposedPorts": {f"{port}/tcp": {} for port in (ports or {}).keys()},
                "HostConfig": {
                    "PortBindings": {
                        f"{container_port}/tcp": [{"HostPort": str(host_port)}]
                        for container_port, host_port in (ports or {}).items()
                    },
                    "Binds": [f"{host}:{container}" for host, container in (volumes or {}).items()]
                }
            }

            if name:
                create_data["Name"] = name

            response = self.http_client.send_request(
                endpoint="/api/docker/v1.24/containers/create",
                method="POST",
                json=create_data
            )
            response.raise_for_status()

            result = response.json()
            container_id = result.get("Id")

            self.logger.info(f"Container created: {container_id}")
            return container_id

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to create container: {error}")
            raise BlackAntDockerError(f"Could not create container: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error creating container: {error}")
            raise BlackAntDockerError(f"Container creation failed: {error}") from error

    def start_container(self, container_id: str) -> bool:
        """Start a container.

        Args:
            container_id: Container ID or name.

        Returns:
            True if started successfully.

        Raises:
            BlackAntDockerError: If start fails.
        """
        try:
            response = self.http_client.send_request(
                endpoint=f"/api/docker/v1.24/containers/{container_id}/start",
                method="POST"
            )
            response.raise_for_status()

            self.logger.info(f"Container started: {container_id}")
            return True

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to start container: {error}")
            raise BlackAntDockerError(f"Could not start container: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error starting container: {error}")
            raise BlackAntDockerError(f"Container start failed: {error}") from error

    def stop_container(self, container_id: str, timeout: int = 10) -> bool:
        """Stop a container.

        Args:
            container_id: Container ID or name.
            timeout: Seconds to wait before killing.

        Returns:
            True if stopped successfully.

        Raises:
            BlackAntDockerError: If stop fails.
        """
        try:
            response = self.http_client.send_request(
                endpoint=f"/api/docker/v1.24/containers/{container_id}/stop?t={timeout}",
                method="POST"
            )
            response.raise_for_status()

            self.logger.info(f"Container stopped: {container_id}")
            return True

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to stop container: {error}")
            raise BlackAntDockerError(f"Could not stop container: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error stopping container: {error}")
            raise BlackAntDockerError(f"Container stop failed: {error}") from error

    def remove_container(self, container_id: str, force: bool = False) -> bool:
        """Remove a container.

        Args:
            container_id: Container ID or name.
            force: Force removal of running container.

        Returns:
            True if removed successfully.

        Raises:
            BlackAntDockerError: If removal fails.
        """
        try:
            params = "?force=true" if force else ""
            response = self.http_client.send_request(
                endpoint=f"/api/docker/v1.24/containers/{container_id}{params}",
                method="DELETE"
            )
            response.raise_for_status()

            self.logger.info(f"Container removed: {container_id}")
            return True

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to remove container: {error}")
            raise BlackAntDockerError(f"Could not remove container: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error removing container: {error}")
            raise BlackAntDockerError(f"Container removal failed: {error}") from error

    def pull_image(self, image: str, tag: str = "latest") -> Dict[str, Any]:
        """Pull Docker image from registry.

        Args:
            image: Image name (e.g., "nginx").
            tag: Image tag.

        Returns:
            Pull result with status.

        Raises:
            BlackAntDockerError: If pull fails.
        """
        try:
            full_image = f"{image}:{tag}"
            response = self.http_client.send_request(
                endpoint=f"/api/docker/v1.24/images/create?fromImage={image}&tag={tag}",
                method="POST",
                req_timeout=300.0
            )
            response.raise_for_status()

            self.logger.info(f"Image pulled: {full_image}")
            return {"image": full_image, "success": True}

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to pull image: {error}")
            raise BlackAntDockerError(f"Could not pull image: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error pulling image: {error}")
            raise BlackAntDockerError(f"Image pull failed: {error}") from error

    def push_image(self, image: str, tag: str = "latest") -> Dict[str, Any]:
        """Push Docker image to registry.

        Args:
            image: Image name.
            tag: Image tag.

        Returns:
            Push result with status.

        Raises:
            BlackAntDockerError: If push fails.
        """
        try:
            full_image = f"{image}:{tag}"
            response = self.http_client.send_request(
                endpoint=f"/api/docker/v1.24/images/{full_image}/push",
                method="POST",
                req_timeout=300.0
            )
            response.raise_for_status()

            self.logger.info(f"Image pushed: {full_image}")
            return {"image": full_image, "success": True}

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to push image: {error}")
            raise BlackAntDockerError(f"Could not push image: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error pushing image: {error}")
            raise BlackAntDockerError(f"Image push failed: {error}") from error

    def inspect_image(self, image: str) -> Dict[str, Any]:
        """Inspect Docker image details.

        Args:
            image: Image name/ID.

        Returns:
            Image inspection data.

        Raises:
            BlackAntDockerError: If inspection fails.
        """
        try:
            response = self.http_client.send_request(
                endpoint=f"/api/docker/v1.24/images/{image}/json",
                method="GET"
            )
            response.raise_for_status()

            image_data = response.json()
            self.logger.debug(f"Image inspected: {image}")
            return image_data

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to inspect image: {error}")
            raise BlackAntDockerError(f"Could not inspect image: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error inspecting image: {error}")
            raise BlackAntDockerError(f"Image inspection failed: {error}") from error

    def get_container_logs(self, container_id: str, follow: bool = False,
                          tail: int = 100) -> str:
        """Get container logs.

        Args:
            container_id: Container ID or name.
            follow: Follow log output.
            tail: Number of lines from end of logs.

        Returns:
            Container logs as string.

        Raises:
            BlackAntDockerError: If getting logs fails.
        """
        try:
            params = f"?stdout=true&stderr=true&tail={tail}"
            if follow:
                params += "&follow=true"

            response = self.http_client.send_request(
                endpoint=f"/api/docker/v1.24/containers/{container_id}/logs{params}",
                method="GET"
            )
            response.raise_for_status()

            logs = response.text
            self.logger.debug(f"Retrieved logs for container: {container_id}")
            return logs

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to get container logs: {error}")
            raise BlackAntDockerError(f"Could not get logs: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error getting logs: {error}")
            raise BlackAntDockerError(f"Get logs failed: {error}") from error

    def get_events(self, since: Optional[str] = None, until: Optional[str] = None,
                  filters: Optional[Dict[str, Any]] = None) -> List[Dict[str, Any]]:
        """Get Docker events.

        Args:
            since: Timestamp to start from.
            until: Timestamp to end at.
            filters: Event filters (type, container, etc.).

        Returns:
            List of Docker events.

        Raises:
            BlackAntDockerError: If getting events fails.
        """
        try:
            params = []
            if since:
                params.append(f"since={since}")
            if until:
                params.append(f"until={until}")
            if filters:
                filters_json = json.dumps(filters)
                params.append(f"filters={filters_json}")

            query_string = "&".join(params)
            endpoint = "/api/docker/v1.24/events"
            if query_string:
                endpoint += f"?{query_string}"

            response = self.http_client.send_request(
                endpoint=endpoint,
                method="GET",
                req_timeout=30.0
            )
            response.raise_for_status()

            # Parse JSONL response (one JSON object per line)
            events = []
            for line in response.text.split('\n'):
                if line.strip():
                    try:
                        event = json.loads(line)
                        events.append(event)
                    except json.JSONDecodeError:
                        pass

            self.logger.debug(f"Retrieved {len(events)} Docker events")
            return events

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to get Docker events: {error}")
            raise BlackAntDockerError(f"Could not get events: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error getting events: {error}")
            raise BlackAntDockerError(f"Get events failed: {error}") from error

    def get_system_df(self) -> Dict[str, Any]:
        """Get Docker system disk usage information.

        Returns:
            System disk usage data.

        Raises:
            BlackAntDockerError: If getting disk usage fails.
        """
        try:
            response = self.http_client.send_request(
                endpoint="/api/docker/v1.24/system/df",
                method="GET"
            )
            response.raise_for_status()

            df_data = response.json()
            self.logger.debug("Retrieved Docker disk usage")
            return df_data

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to get disk usage: {error}")
            raise BlackAntDockerError(f"Could not get disk usage: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error getting disk usage: {error}")
            raise BlackAntDockerError(f"Get disk usage failed: {error}") from error

    def inspect_container(self, container_id: str) -> Dict[str, Any]:
        """Inspect container details.

        Args:
            container_id: Container ID or name.

        Returns:
            Container inspection data.

        Raises:
            BlackAntDockerError: If inspection fails.
        """
        try:
            response = self.http_client.send_request(
                endpoint=f"/api/docker/v1.24/containers/{container_id}/json",
                method="GET"
            )
            response.raise_for_status()

            container_data = response.json()
            self.logger.debug(f"Container inspected: {container_id}")
            return container_data

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to inspect container: {error}")
            raise BlackAntDockerError(f"Could not inspect container: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error inspecting container: {error}")
            raise BlackAntDockerError(f"Container inspection failed: {error}") from error

    def get_container_stats(self, container_id: str, stream: bool = False) -> Dict[str, Any]:
        """Get container resource usage statistics.

        Args:
            container_id: Container ID or name.
            stream: Whether to stream stats continuously.

        Returns:
            Container resource statistics.

        Raises:
            BlackAntDockerError: If getting stats fails.
        """
        try:
            params = "?stream=false"
            if stream:
                params = "?stream=true"

            response = self.http_client.send_request(
                endpoint=f"/api/docker/v1.24/containers/{container_id}/stats{params}",
                method="GET"
            )
            response.raise_for_status()

            if stream:
                # Return iterator for streaming stats
                def stats_iterator():
                    for line in response.iter_lines():
                        if line:
                            try:
                                yield json.loads(line.decode())
                            except json.JSONDecodeError:
                                pass
                return stats_iterator()
            else:
                stats = response.json()
                self.logger.debug(f"Retrieved stats for container: {container_id}")
                return stats

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to get container stats: {error}")
            raise BlackAntDockerError(f"Could not get stats: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error getting stats: {error}")
            raise BlackAntDockerError(f"Get stats failed: {error}") from error

    def prune_containers(self, filters: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """Remove unused containers.

        Args:
            filters: Prune filters.

        Returns:
            Prune results with space reclaimed.

        Raises:
            BlackAntDockerError: If pruning fails.
        """
        try:
            prune_data = {}
            if filters:
                prune_data["filters"] = filters

            response = self.http_client.send_request(
                endpoint="/api/docker/v1.24/containers/prune",
                method="POST",
                json=prune_data if prune_data else None
            )
            response.raise_for_status()

            prune_result = response.json()
            space_reclaimed = prune_result.get('SpaceReclaimed', 0)
            self.logger.info(f"Containers pruned: {space_reclaimed} bytes reclaimed")
            return prune_result

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to prune containers: {error}")
            raise BlackAntDockerError(f"Could not prune containers: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error pruning containers: {error}")
            raise BlackAntDockerError(f"Container prune failed: {error}") from error

    def prune_images(self, dangling_only: bool = True) -> Dict[str, Any]:
        """Remove unused images.

        Args:
            dangling_only: Only remove dangling images.

        Returns:
            Prune results with space reclaimed.

        Raises:
            BlackAntDockerError: If pruning fails.
        """
        try:
            filters = {}
            if dangling_only:
                filters["dangling"] = ["true"]

            prune_data = {"filters": filters} if filters else {}

            response = self.http_client.send_request(
                endpoint="/api/docker/v1.24/images/prune",
                method="POST",
                json=prune_data if prune_data else None
            )
            response.raise_for_status()

            prune_result = response.json()
            space_reclaimed = prune_result.get('SpaceReclaimed', 0)
            self.logger.info(f"Images pruned: {space_reclaimed} bytes reclaimed")
            return prune_result

        except HTTPConnectionError as error:
            self.logger.error(f"Failed to prune images: {error}")
            raise BlackAntDockerError(f"Could not prune images: {error}") from error
        except Exception as error:
            self.logger.error(f"Unexpected error pruning images: {error}")
            raise BlackAntDockerError(f"Image prune failed: {error}") from error

    def build_service(self,
                     service_name: str,
                     impl_path: str = "src/calculation/impl",
                     dockerfile_path: str = "Dockerfile",
                     tag: Optional[str] = None,
                     push: bool = True,
                     register_service: bool = True) -> Dict[str, Any]:
        """Build és deploy service Docker image.

        Ez az 5 core metódus egyike! Build Docker image a user implementation-ből,
        upload registry-be, és regisztrálja a ServiceManager-ben.

        Args:
            service_name: Service név (alphanumeric + hyphens/underscores)
            impl_path: User implementation mappa útvonala
            dockerfile_path: Dockerfile útvonala (repository root-ból)
            tag: Verzió tag (auto-generált ha None: v1.0.0-{timestamp})
            push: Feltöltés env.blackant.app registry-be
            register_service: Automatikus service regisztráció ServiceManager-ben

        Returns:
            dict: Build és deployment információk
                {
                    "image_name": "env.blackant.app/systemdevelopers/service_name",
                    "tag": "v1.0.0-20250105-123456",
                    "full_image": "env.blackant.app/systemdevelopers/service_name:v1.0.0-20250105-123456",
                    "image_id": "sha256:...",
                    "size": 125000000,
                    "pushed": True,
                    "registry_url": "env.blackant.app",
                    "service_id": "uuid-from-servicemanager",
                    "service_registered": True
                }

        Raises:
            BlackAntDockerError: Build, push vagy regisztrációs hiba esetén

        Example:
            >>> auth = BlackAntAuth(user="developer", password="xxx")
            >>> client = BlackAntDockerClient(auth=auth)
            >>> result = client.build_service(
            ...     service_name="my-calculation",
            ...     impl_path="src/calculation/impl",
            ...     tag="v1.0.0"
            ... )
            >>> print(result["full_image"])
            env.blackant.app/systemdevelopers/my-calculation:v1.0.0
            >>> print(result["service_id"])
            abc-123-def-456
        """

        self.logger.info(f"Building service: {service_name}")

        try:
            # 1. Build Docker image local-ban
            build_result = self.image_builder.build_service(
                service_name=service_name,
                impl_path=impl_path,
                dockerfile_path=dockerfile_path,
                tag=tag,
                push_to_registry=push
            )

            self.logger.info(f"Image build completed: {build_result['full_image']}")

            # 2. Role assignment after successful push (Balázs requirement)
            role_assigned = False
            if build_result.get("pushed", False):
                try:
                    # Get user token for role assignment
                    user_token = self.auth.get_token() if self.auth else None
                    if user_token:
                        role_manager = get_role_assignment_manager()
                        role_assigned = role_manager.assign_role_after_publish(
                            user_token=user_token,
                            service_name=service_name,
                            metadata={
                                "image": build_result.get("full_image"),
                                "registry_url": build_result.get("registry_url")
                            }
                        )
                        if role_assigned:
                            self.logger.info(f"Role 'science_module' assigned after push for service: {service_name}")
                        else:
                            self.logger.warning(f"Role assignment failed for service: {service_name}")
                    else:
                        self.logger.warning("No user token available for role assignment")
                except Exception as role_error:
                    self.logger.warning(f"Role assignment error (non-fatal): {role_error}")
                    # Continue - role assignment failure shouldn't block the build

            # 3. Service registration preparation
            service_registered = False
            service_id = None

            # 4. Service registration in ServiceManager (if requested and push successful)
            if register_service and build_result.get("pushed", False):
                try:
                    service_config = {
                        "name": service_name,
                        "type": "calculation",
                        "image": {
                            "container": "systemdevelopers",  # Registry namespace fix
                            "name": service_name,
                            "tag": build_result["tag"]
                        },
                        "environments": {
                            "BLACKANT_ENV": "production",
                            "LOG_LEVEL": "INFO",
                            "SERVICE_NAME": service_name
                        },
                        "networks": ["blackant_network"],
                        "parent": None,
                        "resource_config": {
                            "use_gpu": False,
                            "cpu_limit": 1.0,
                            "ram_limit": "512M",
                            "disk_limit": "1G",
                            "node_label": None
                        }
                    }

                    self.logger.debug(f"Registering service with config: {service_config}")

                    # ServiceManager API hívás
                    response = self.http_client.send_request(
                        endpoint="/api/v1/services",
                        method="POST",
                        json=service_config
                    )

                    if response.status_code == 200 or response.status_code == 201:
                        response_data = response.json()
                        service_id = response_data.get("uuid") or response_data.get("id")
                        service_registered = True
                        self.logger.info(f"Service registered successfully: {service_name} -> {service_id}")
                    else:
                        self.logger.warning(f"Service registration failed: {response.status_code} - {response.text}")

                except Exception as reg_error:
                    self.logger.warning(f"Service registration failed: {reg_error}")
                    # Folytatjuk annak ellenére, hogy a regisztráció nem sikerült

            # 5. Collect complete result
            result = {
                **build_result,  # All build results (image_name, tag, etc.)
                "service_id": service_id,
                "service_registered": service_registered,
                "role_assigned": role_assigned,
                "build_success": True
            }

            # 6. Success log
            self.logger.info(f"Build service completed: {service_name}")
            if role_assigned:
                self.logger.info(f"Role 'science_module' assigned to user")
            if service_registered:
                self.logger.info(f"Service registered with ID: {service_id}")

            return result

        except Exception as e:
            error_msg = f"Build service failed for {service_name}: {e}"
            self.logger.error(error_msg)
            raise BlackAntDockerError(error_msg) from e
