from __future__ import annotations

import os
import shlex
from dataclasses import dataclass
from pathlib import Path
from typing import Any

from .spec import ConfigPatch, EngineLaunchSpec


@dataclass(frozen=True)
class LaunchRecipe:
    argv: list[str]
    env: dict[str, str]
    cwd: str | None
    base_url: str
    healthcheck_path: str
    ready_timeout_s: float
    request_timeout_s: float


def _normalize_flag_name(name: str) -> str:
    return str(name).strip().replace("_", "-")


def _serialize_flag_parts(name: str, value: Any) -> list[str]:
    flag = f"--{_normalize_flag_name(name)}"
    if value is None:
        return []
    if isinstance(value, bool):
        return [flag] if value else [f"--no-{_normalize_flag_name(name)}"]
    if isinstance(value, list):
        return [flag, *[str(item) for item in value]]
    return [flag, str(value)]


def build_launch_recipe(spec: EngineLaunchSpec, patch: ConfigPatch) -> LaunchRecipe:
    env = dict(os.environ)
    env.update(spec.base_envs)
    env.update(patch.env_patch)
    flags = dict(spec.base_flags)
    flags.update(patch.flag_patch)
    argv = [spec.exec_path, *spec.launch_args]
    for key, value in flags.items():
        argv.extend(_serialize_flag_parts(key, value))
    cwd = None
    if spec.cwd:
        cwd = str(Path(spec.cwd).expanduser())
    return LaunchRecipe(
        argv=argv,
        env={str(key): str(value) for key, value in env.items()},
        cwd=cwd,
        base_url=spec.base_url,
        healthcheck_path=spec.healthcheck_path,
        ready_timeout_s=spec.ready_timeout_s,
        request_timeout_s=spec.request_timeout_s,
    )


def shell_join(argv: list[str]) -> str:
    return " ".join(shlex.quote(item) for item in argv)
