#!/usr/bin/env python3

import configparser
import pathlib
import subprocess
import time

import click


_CONFIG_FILE = pathlib.Path.home() / ".config" / "livecd-rootfs" / "build-livefs.conf"


def _read_config() -> dict[str, str]:
    cp = configparser.ConfigParser()
    cp.read(_CONFIG_FILE)
    return dict(cp["defaults"]) if "defaults" in cp else {}


@click.command(
    context_settings={"ignore_unknown_options": True, "allow_extra_args": True}
)
@click.option("--suite", required=True, help="Ubuntu suite/series (e.g. noble)")
@click.option(
    "--vm-name",
    default=None,
    help="LXD VM name (default: livefs-builder-{suite})",
)
@click.option(
    "--http-proxy",
    default=None,
    help="HTTP proxy URL for apt inside the VM (also read from build-livefs.conf)",
)
@click.argument("extra_args", nargs=-1, type=click.UNPROCESSED)
def main(suite, vm_name, http_proxy, extra_args):
    livecd_rootfs_root = pathlib.Path(__file__).resolve().parent.parent
    vm_name = vm_name or f"livefs-builder-{suite}"
    host_conf = (
        pathlib.Path.home() / ".config" / "livecd-rootfs" / "build-livefs.conf"
    )

    if http_proxy is None:
        http_proxy = _read_config().get("http-proxy")

    result = subprocess.run(["lxc", "info", vm_name], capture_output=True)
    if result.returncode != 0:
        launch_cmd = [
            "lxc", "launch", f"ubuntu-daily:{suite}", vm_name, "--vm",
            "--config", "limits.cpu=4",
            "--config", "limits.memory=8GiB",
            "--device", "root,size=100GiB",
        ]
        user_data = "#cloud-config\npackage_update: true\n"
        if http_proxy is not None:
            user_data += (
                "apt:\n"
                f"  http_proxy: {http_proxy}\n"
                f"  https_proxy: {http_proxy}\n"
            )
        launch_cmd += ["--config", f"user.user-data={user_data}"]
        subprocess.run(launch_cmd, check=True)

    device_info = subprocess.run(
        ["lxc", "config", "device", "show", vm_name],
        capture_output=True,
        text=True,
        check=True,
    ).stdout
    if "livecd-rootfs" not in device_info:
        subprocess.run(
            [
                "lxc",
                "config",
                "device",
                "add",
                vm_name,
                "livecd-rootfs",
                "disk",
                f"source={livecd_rootfs_root}",
                "path=/srv/livecd-rootfs",
            ],
            check=True,
        )

    info = subprocess.run(
        ["lxc", "info", vm_name], capture_output=True, text=True, check=True
    ).stdout
    if "Status: STOPPED" in info:
        subprocess.run(["lxc", "start", vm_name], check=True)

    for _ in range(30):
        result = subprocess.run(
            ["lxc", "exec", vm_name, "--", "true"], capture_output=True
        )
        if result.returncode == 0:
            break
        time.sleep(2)
    else:
        raise click.ClickException(f"VM {vm_name!r} did not become ready in time")

    subprocess.run(
        ["lxc", "exec", vm_name, "--", "cloud-init", "status", "--wait"], check=True
    )

    subprocess.run(
        ["lxc", "exec", vm_name, "--", "apt-get", "install", "-y", "livecd-rootfs"],
        check=True,
    )

    if host_conf.exists():
        subprocess.run(
            [
                "lxc",
                "exec",
                vm_name,
                "--",
                "mkdir",
                "-p",
                "/root/.config/livecd-rootfs",
            ],
            check=True,
        )
        subprocess.run(
            [
                "lxc",
                "file",
                "push",
                str(host_conf),
                f"{vm_name}/root/.config/livecd-rootfs/build-livefs.conf",
            ],
            check=True,
        )

    subprocess.run(
        [
            "lxc",
            "exec",
            vm_name,
            "--",
            "/srv/livecd-rootfs/live-build/build-livefs",
            "--suite",
            suite,
            *extra_args,
        ],
        check=True,
    )


if __name__ == "__main__":
    main()
