# Copyright: (c) 2024, Luca Bilke <luca@bil.ke>
# MIT License (see LICENSE)

from __future__ import annotations

import copy
from dataclasses import replace
from typing import TYPE_CHECKING, Any, Callable

from ansible_collections.ssnailed.ez_compose.plugins.module_utils.common import (  # type: ignore[reportMissingTypeStubs]
    recursive_update,
    update_project,
)

if TYPE_CHECKING:
    from ansible_collections.ssnailed.ez_compose.plugins.module_utils.common import (  # type: ignore[reportMissingTypeStubs]
        State,
    )

BASE_ARGS = {
    "name": {"type": "str", "required": True},
    "image": {"type": "str", "required": True},
    "defaults": {"type": "dict"},
}


def apply_base(state: State, params: dict[str, Any]) -> State:
    project_name = state.module.params["name"]

    new: dict[str, Any] = {
        "container_name": f"{project_name}_{params["name"]}",
        "hostname": f"{project_name}_{params["name"]}",
        "image": params["image"],
        "restart": "unless-stopped",
        "environment": {},
        "labels": {},
        "volumes": [],
        "networks": {
            "internal": None,
        },
    }

    return update(state, new)


def set_defaults(state: State, params: dict[str, Any]) -> State:
    container_name = params["name"]
    defaults = params.get("defaults", {})
    project = copy.deepcopy(state.after)
    services = project["services"]
    service = services[container_name]

    _ = recursive_update(service, defaults)

    services.update({container_name: service})

    return replace(state, after=project)


def update(state: State, update: dict[str, Any]) -> State:
    project = copy.deepcopy(state.after)
    service_name = state.module.params["name"]

    _ = recursive_update(project["services"][service_name], update)

    return replace(state, after=project)


def run_helper(
    state: State,
    params: dict[str, Any],
    helper: Callable[[State, dict[str, Any]], State] = lambda x, _: x,
) -> State:
    state = apply_base(state, params)
    state = set_defaults(state, params)
    state = helper(state, params)
    return update_project(state)