import os 
import subprocess 
from pathlib import Path
import sys 
import socket
from zyro.core.parser import laod_yaml_file, get_environment_config

# User writes his own Dockerfile in the project root.
# The Dockerfile should be named 'Dockerfile' and placed in the project root.
# The Dockerfile should contain the necessary instructions to build the application image.
# The user can specify the Dockerfile path in the config.yaml file under the 'docker' section.
# The Dockerfile should expose the necessary ports and set the entrypoint for the application.
# The user can run the Docker container using the command: zyro dockerize <path_to_config_file>
# The application will be built and run in a Docker container based on the provided Dockerfile.
# We should ensure that the Dockerfile is valid and contains the necessary instructions to build the application image.
# We should also run the `zyro run -config=<path_to_config_file>` command to start the application in the Docker container.
# Ensure that the 8000 port is not already in use on the host machine.

def is_port_available(port: int) -> bool:
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        return s.connect_ex(("localhost", port)) != 0 
    
def validate_dockerfile(dockerfile_path: Path):
    if not dockerfile_path.exists():
        print(f"Dockerfile not found at {dockerfile_path}")
        sys.exit(1) 

def build_image(dockerfile_path: Path, image_tag: str):
    try:
        subprocess.run(
            ["docker", "build", "-t", image_tag, "-f", str(dockerfile_path), "."],
            check=True
        )
        print(f"Image {image_tag} built successfully.")
    except subprocess.CalledProcessError as e:
        print(f"Error building Docker image: {e}")
        sys.exit(1)

def run_container(image_tag: str, config_path: str):
    try:
        subprocess.run(
            ["docker", "run", "-d", "-p", "8000:8000", image_tag, "zyro", "run", f"--config={config_path}"],
            check=True
        )
        print(f"Container running with image {image_tag}.")
    except subprocess.CalledProcessError as e:
        print(f"Error running Docker container: {e}")
        sys.exit(1)

def dockerize(config_path: str):
    config = laod_yaml_file(config_path)
    docker_config = config.get('docker', {})
    dockerfile_path = Path(docker_config.get('dockerfile', 'Dockerfile'))
    
    validate_dockerfile(dockerfile_path)

    if not is_port_available(8000):
        print("Port 8000 is already in use. Please free the port and try again.")
        sys.exit(1)

    image_tag = f"zyro_app:{os.path.basename(config_path).replace('.yaml', '')}"
    build_image(dockerfile_path, image_tag) 
    print(f"Running the Docker container with image {image_tag}...")
    run_container(image_tag, config_path) 