"""Docker-based PostgreSQL mock for local self-testing.

Provides a throwaway Postgres container that the backend can connect to during
external-connection tests. The container is bound to 0.0.0.0:5432 on the Docker
host, so the host IP must be reachable from the backend server.
"""

import socket
import subprocess
import sys
import time
from typing import Optional

DEFAULT_IMAGE = "postgres:16-alpine"
DEFAULT_CONTAINER = "lzwcai_mcp_agile_db_third_mock_pg"
DEFAULT_PORT = 5432
DEFAULT_DATABASE = "postgres"
DEFAULT_USERNAME = "postgres"
DEFAULT_PASSWORD = "postgres"


def _run(args: list, check: bool = False, capture: bool = True) -> subprocess.CompletedProcess:
    """Run a shell command and return the result."""
    return subprocess.run(
        args,
        check=check,
        capture_output=capture,
        text=True,
        shell=False,
    )


def host_ip(prefer_prefixes: Optional[list] = None) -> str:
    """Return a non-loopback IPv4 address of this machine.

    Prefers addresses starting with the given prefixes so users can steer the
    result toward the network segment that the backend can reach.
    """
    prefer_prefixes = prefer_prefixes or ["192.168.", "10.", "172."]
    hostname = socket.gethostname()
    _, _, ips = socket.gethostbyname_ex(hostname)
    # Prefer addresses matching a requested prefix, then any non-loopback.
    for prefix in prefer_prefixes:
        for ip in ips:
            if ip.startswith(prefix) and not ip.startswith("127."):
                return ip
    for ip in ips:
        if not ip.startswith("127."):
            return ip
    raise RuntimeError("Could not find a non-loopback IPv4 address on this host")


def is_running(container: str = DEFAULT_CONTAINER) -> bool:
    """Check whether the mock container is currently running."""
    result = _run(["docker", "ps", "--filter", f"name={container}", "--format", "{{.Names}}"])
    return container in result.stdout


def start(
    container: str = DEFAULT_CONTAINER,
    port: int = DEFAULT_PORT,
    username: str = DEFAULT_USERNAME,
    password: str = DEFAULT_PASSWORD,
    database: str = DEFAULT_DATABASE,
    image: str = DEFAULT_IMAGE,
) -> str:
    """Start the Postgres mock container if not already running.

    Returns the host IP that should be supplied to backend connection tests.
    """
    if is_running(container):
        print(f"Mock DB container '{container}' is already running.")
        return host_ip()

    # Remove any stale container with the same name.
    _run(["docker", "rm", "-f", container], check=False)

    print(f"Starting mock Postgres container '{container}' (image={image})...")
    _run(
        [
            "docker", "run", "-d",
            "--name", container,
            "-p", f"{port}:{port}",
            "-e", f"POSTGRES_USER={username}",
            "-e", f"POSTGRES_PASSWORD={password}",
            "-e", f"POSTGRES_DB={database}",
            image,
        ],
        check=True,
    )

    print("Waiting for Postgres to become ready...")
    deadline = time.time() + 30
    while time.time() < deadline:
        result = _run(
            ["docker", "exec", container, "pg_isready", "-U", username],
            check=False,
        )
        if result.returncode == 0:
            break
        time.sleep(0.5)
    else:
        stop(container)
        raise RuntimeError("Postgres mock failed to become ready within 30s")

    ip = host_ip()
    print(f"Mock Postgres is ready at {ip}:{port} (user={username}, password={password}, db={database})")
    return ip


def stop(container: str = DEFAULT_CONTAINER) -> None:
    """Stop and remove the mock Postgres container."""
    print(f"Stopping mock DB container '{container}'...")
    _run(["docker", "stop", "-t", "5", container], check=False)
    _run(["docker", "rm", "-f", container], check=False)


def main():
    if len(sys.argv) < 2:
        print("Usage: python -m lzwcai_mcp_agile_db_third.mock_db [start|stop|ip]")
        sys.exit(1)
    cmd = sys.argv[1].lower()
    if cmd == "start":
        start()
    elif cmd == "stop":
        stop()
    elif cmd in ("ip", "host"):
        print(host_ip())
    elif cmd == "status":
        print("running" if is_running() else "stopped")
    else:
        print(f"Unknown command: {cmd}")
        sys.exit(1)


if __name__ == "__main__":
    main()
