# This code is part of the Ansible collection community.docker, but is an independent component.
# This particular file, and this file only, is based on the Docker SDK for Python (https://github.com/docker/docker-py/)
#
# Copyright (c) 2016-2025 Docker, Inc.
#
# It is licensed under the Apache 2.0 license (see LICENSES/Apache-2.0.txt in this collection)
# SPDX-License-Identifier: Apache-2.0

# Note that this module util is **PRIVATE** to the collection. It can have breaking changes at any time.
# Do not use this from other collections or standalone plugins/modules!

from __future__ import annotations

import hashlib
import json
import os

from ..constants import DEFAULT_UNIX_SOCKET, IS_WINDOWS_PLATFORM
from ..utils.config import find_config_file, get_default_config_file
from ..utils.utils import parse_host

METAFILE = "meta.json"


def get_current_context_name_with_source() -> tuple[str, str]:
    if os.environ.get("DOCKER_HOST"):
        return "default", "DOCKER_HOST environment variable set"
    if os.environ.get("DOCKER_CONTEXT"):
        return os.environ["DOCKER_CONTEXT"], "DOCKER_CONTEXT environment variable set"
    docker_cfg_path = find_config_file()
    if docker_cfg_path:
        try:
            with open(docker_cfg_path, "rt", encoding="utf-8") as f:
                return (
                    json.load(f).get("currentContext", "default"),
                    f"configuration file {docker_cfg_path}",
                )
        except Exception:  # pylint: disable=broad-exception-caught
            pass
    return "default", "fallback value"


def get_current_context_name() -> str:
    return get_current_context_name_with_source()[0]


def write_context_name_to_docker_config(name: str | None = None) -> Exception | None:
    if name == "default":
        name = None
    docker_cfg_path = find_config_file()
    config = {}
    if docker_cfg_path:
        try:
            with open(docker_cfg_path, "rt", encoding="utf-8") as f:
                config = json.load(f)
        except Exception as e:  # pylint: disable=broad-exception-caught
            return e
    current_context = config.get("currentContext", None)
    if current_context and not name:
        del config["currentContext"]
    elif name:
        config["currentContext"] = name
    else:
        return None
    if not docker_cfg_path:
        docker_cfg_path = get_default_config_file()
    try:
        with open(docker_cfg_path, "wt", encoding="utf-8") as f:
            json.dump(config, f, indent=4)
        return None
    except Exception as e:  # pylint: disable=broad-exception-caught
        return e


def get_context_id(name: str) -> str:
    return hashlib.sha256(name.encode("utf-8")).hexdigest()


def get_context_dir() -> str:
    docker_cfg_path = find_config_file() or get_default_config_file()
    return os.path.join(os.path.dirname(docker_cfg_path), "contexts")


def get_meta_dir(name: str | None = None) -> str:
    meta_dir = os.path.join(get_context_dir(), "meta")
    if name:
        return os.path.join(meta_dir, get_context_id(name))
    return meta_dir


def get_meta_file(name: str) -> str:
    return os.path.join(get_meta_dir(name), METAFILE)


def get_tls_dir(name: str | None = None, endpoint: str = "") -> str:
    context_dir = get_context_dir()
    if name:
        return os.path.join(context_dir, "tls", get_context_id(name), endpoint)
    return os.path.join(context_dir, "tls")


def get_context_host(path: str | None = None, tls: bool = False) -> str:
    host = parse_host(path, IS_WINDOWS_PLATFORM, tls)
    if host == DEFAULT_UNIX_SOCKET and host.startswith("http+"):
        # remove http+ from default docker socket url
        host = host[5:]
    return host
