"""Docker build execution utilities."""

from __future__ import annotations

import logging
from pathlib import Path
from typing import TYPE_CHECKING, Any

from aida_mcp.output import format_command_summary
from aida_mcp.tools.docker.service_detection import get_build_contexts_for_service, get_secrets_for_service
from aida_mcp.tools.docker.wheel_testing import test_wheel_selection
from aida_mcp.utils.command_runner import run_command

if TYPE_CHECKING:
    from mcp.server.fastmcp import Context as MCPContext

    Context = MCPContext[Any, Any, Any]

logger = logging.getLogger(__name__)


async def test_service_build(workspace_root: Path, service_dir: str, platforms: str = "linux/amd64,linux/arm64") -> str:
    """
    Test Docker build for a specific service.

    Args:
        workspace_root: Workspace root path
        service_dir: Service directory relative to workspace root (e.g., "microservices/gen-ai")
        platforms: Platform specification for multi-platform builds

    Returns:
        Formatted build results
    """
    dockerfile_path = workspace_root / service_dir / "Dockerfile"
    if not dockerfile_path.exists():
        return f"⚠️  {service_dir}: No Dockerfile found, skipping"

    results = [f"🔨 Building {service_dir}...", ""]

    # Quick wheel selection test for tabular-exporter (catches issues in seconds)
    wheel_test_passed, wheel_test_msg = await test_wheel_selection(workspace_root, service_dir)
    if wheel_test_msg:
        results.append(wheel_test_msg)
        results.append("")
        if not wheel_test_passed:
            results.append(f"❌ {service_dir}: WHEEL SELECTION TEST FAILED - Skipping Docker build")
            return "\n".join(results)

    # For local testing, if multiple platforms specified, build for single platform
    # (--load doesn't work with multi-platform builds)
    platform_list = [p.strip() for p in platforms.split(",")]
    is_multi_platform = len(platform_list) > 1
    test_platform = platform_list[0] if is_multi_platform else platforms

    # Get build contexts and secrets for this service
    build_contexts = get_build_contexts_for_service(service_dir)
    secrets = get_secrets_for_service(service_dir)

    # Build docker buildx command (matching pipeline behavior)
    cmd = [
        "docker",
        "buildx",
        "build",
        "--platform",
        test_platform,  # Use single platform for local testing
        "--progress=plain",
        "--load",  # Load into local Docker (for local testing)
        "-f",
        str(dockerfile_path),
        "--tag",
        f"{service_dir.replace('/', '-')}:test-build",
    ]

    # Add build contexts if needed
    for context in build_contexts:
        cmd.extend(["--build-context", context])

    # Add secrets if needed
    for secret in secrets:
        cmd.extend(["--secret", secret])

    # Add build args (common ones)
    cmd.extend(["--build-arg", "REPO_PREFIX="])

    # Set context directory
    cmd.append(str(workspace_root / service_dir))

    # Run docker buildx build
    # Use longer timeout for docker builds (they can take a while, especially multi-platform)
    cmd_result = await run_command(
        cmd, workspace_root, timeout=1800, env={"DOCKER_BUILDKIT": "1"}, ctx=None, step_name=None
    )
    exit_code = cmd_result.exit_code
    stdout = cmd_result.stdout
    stderr = cmd_result.stderr

    # Check for wheel-related errors in output
    wheel_errors: list[str] = []
    combined_output = stdout + stderr
    if "not a supported wheel on this platform" in combined_output:
        wheel_errors.append("⚠️  Platform wheel mismatch detected")
    # Only flag macOS wheels if they're actually being processed/installed (not just mentioned in logs)
    if "macosx" in combined_output.lower() and "linux" in platforms.lower():
        # Check if it's an actual error about macOS wheels, not just a mention
        if "ERROR" in combined_output and "macosx" in combined_output.lower():
            wheel_errors.append("⚠️  macOS wheels detected in Linux build")
        # Also check if macOS wheels are being processed (installed)
        if "Processing" in combined_output and "macosx" in combined_output.lower():
            wheel_errors.append("⚠️  macOS wheels being processed in Linux build")

    # Format output
    command_str = " ".join(cmd)
    result = format_command_summary(command_str, exit_code, stdout, stderr, log_path=cmd_result.log_path)
    results.append(result)

    # Add wheel error warnings if any
    if wheel_errors:
        results.append("")
        results.append("🔍 Wheel Selection Issues Detected:")
        for error in wheel_errors:
            results.append(f"   {error}")

    # Summary for this service
    results.append("")
    if exit_code == 0:
        results.append(f"✅ {service_dir}: BUILD PASSED")
    else:
        results.append(f"❌ {service_dir}: BUILD FAILED")

    return "\n".join(results)


async def test_docker_compose_build(
    workspace_root: Path,
    compose_files: list[str] | None = None,
) -> str:
    """
    Fallback: Test docker builds using docker compose build.

    Args:
        workspace_root: Workspace root path
        compose_files: Optional list of docker-compose files to use

    Returns:
        Formatted build results
    """
    # Check if docker-compose.yaml exists
    default_compose = workspace_root / "docker-compose.yaml"
    if not default_compose.exists():
        return f"❌ docker-compose.yaml not found at {default_compose}"

    results = [
        "🐳 Testing Docker Builds (docker-compose fallback)",
        "=" * 60,
        "",
        "⚠️  Using docker-compose build (no individual service Dockerfiles detected)",
        "",
    ]

    # Build docker compose command
    cmd = ["docker", "compose"]

    # Add compose files if specified
    if compose_files:
        for compose_file in compose_files:
            cmd.extend(["-f", compose_file])

    cmd.append("build")

    # Run docker compose build
    cmd_result = await run_command(cmd, workspace_root, timeout=1800, ctx=None, step_name=None)
    exit_code = cmd_result.exit_code
    stdout = cmd_result.stdout
    stderr = cmd_result.stderr

    # Format output
    command_str = " ".join(cmd)
    result = format_command_summary(command_str, exit_code, stdout, stderr, log_path=cmd_result.log_path)
    results.append(result)

    # Summary
    results.append("")
    results.append("=" * 60)
    if exit_code == 0:
        results.append("✅ DOCKER BUILD PASSED")
    else:
        results.append("❌ DOCKER BUILD FAILED - Check errors above")

    return "\n".join(results)
