"""Docker build service for building images from Dockerfiles."""

import logging
import subprocess

logger = logging.getLogger(__name__)


def build_image(
    instance_dir: str, dockerfile: str, tag: str, build_context: dict | None = None
) -> tuple[int, str, str]:
    """Build a Docker image from a Dockerfile.

    Args:
        instance_dir: Directory containing the Dockerfile
        dockerfile: Dockerfile content
        tag: Image tag to apply
        build_context: Optional build context files {path: content}

    Returns:
        Tuple of (returncode, stdout, stderr)
    """
    from pathlib import Path

    # Defensive: normalise any CRLF that may have crept in from manifest DB
    # strings — Docker's legacy builder treats \r as a character after the
    # backslash, breaking RUN continuations and producing
    # "unknown instruction" errors.
    dockerfile = dockerfile.replace("\r\n", "\n").replace("\r", "\n")

    # Write Dockerfile
    dockerfile_path = Path(instance_dir) / "Dockerfile"
    dockerfile_path.write_text(dockerfile, newline="\n")
    logger.debug("Wrote Dockerfile to %s (%d bytes)", dockerfile_path, len(dockerfile))

    # Write build context files
    if build_context:
        for file_path, content in build_context.items():
            full_path = Path(instance_dir) / file_path
            # Security: ensure path doesn't escape instance_dir
            try:
                full_path.resolve().relative_to(Path(instance_dir).resolve())
            except ValueError:
                logger.error(
                    "Build context file path escapes instance directory: %s", file_path
                )
                raise ValueError(
                    f"Build context file path '{file_path}' escapes instance directory"
                )

            full_path.parent.mkdir(parents=True, exist_ok=True)
            normalized = content.replace("\r\n", "\n").replace("\r", "\n")
            full_path.write_text(normalized, newline="\n")
            logger.debug("Wrote build context file: %s", full_path)

    # Build image
    logger.debug("Building Docker image with tag: %s", tag)
    cmd = [
        "docker",
        "build",
        "-t",
        tag,
        "-f",
        str(dockerfile_path),
        instance_dir,
    ]

    try:
        result = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
            timeout=300,  # 5 minute timeout for builds
        )
        logger.debug("Docker build completed: returncode=%d", result.returncode)
        if result.returncode != 0:
            logger.error("Docker build failed: %s", result.stderr[:1000])
        return result.returncode, result.stdout, result.stderr
    except subprocess.TimeoutExpired:
        logger.error("Docker build timed out after 300 seconds")
        return 1, "", "Build timed out after 300 seconds"
    except Exception as exc:
        logger.exception("Docker build failed: %s", exc)
        return 1, "", str(exc)
