# Copyright (C) 2019 QuantStack and the Mamba contributors.
# Copyright (C) 2022 Anaconda, Inc
# Copyright (C) 2023 conda
# SPDX-License-Identifier: BSD-3-Clause

# TODO: Temporarily vendored from mamba.utils v0.19 on 2021.12.02
# Decide what to do with it when we split into a plugin
# 2022.02.15: updated vendored parts to v0.21.2
# 2022.11.14: only keeping channel prioritization and context initialization logic now

import logging
from importlib.metadata import version
from typing import Dict

import libmambapy as api
from conda.base.constants import ChannelPriority
from conda.base.context import context

log = logging.getLogger(f"conda.{__name__}")


def mamba_version():
    return version("libmambapy")


def _get_base_url(url, name=None):
    tmp = url.rsplit("/", 1)[0]
    if name:
        if tmp.endswith(name):
            return tmp.rsplit("/", 1)[0]
    return tmp


def set_channel_priorities(index: Dict[str, "_ChannelRepoInfo"], has_priority: bool = None):
    """
    This function was part of mamba.utils.load_channels originally.
    We just split it to reuse it a bit better.
    """
    if has_priority is None:
        has_priority = context.channel_priority in [
            ChannelPriority.STRICT,
            ChannelPriority.FLEXIBLE,
        ]

    subprio_index = len(index)
    if has_priority:
        # max channel priority value is the number of unique channels
        channel_prio = len({info.channel.canonical_name for info in index.values()})
        current_channel = next(iter(index.values())).channel.canonical_name

    for info in index.values():
        # add priority here
        if has_priority:
            if info.channel.canonical_name != current_channel:
                channel_prio -= 1
                current_channel = info.channel.canonical_name
            priority = channel_prio
        else:
            priority = 0
        if has_priority:
            # NOTE: -- this is the whole reason we are vendoring this file --
            # We are patching this from 0 to 1, starting with mamba 0.19
            # Otherwise, test_create::test_force_remove fails :shrug:
            subpriority = 1
        else:
            subpriority = subprio_index
            subprio_index -= 1

        if not context.json:
            log.debug(
                "Channel: %s, platform: %s, prio: %s : %s",
                info.channel,
                info.channel.subdir,
                priority,
                subpriority,
            )
        info.repo.set_priority(priority, subpriority)

    return index


def init_api_context() -> api.Context:
    api_ctx = api.Context()

    # Output params
    # We use this getattr() trick to guarantee backwards compatibility
    # with libmambapy <=1.4.2; 1.4.3+ grouped some settings together
    output_params = getattr(api_ctx, "output_params", api_ctx)
    output_params.json = context.json
    output_params.quiet = context.quiet
    output_params.verbosity = context.verbosity
    api_ctx.set_verbosity(context.verbosity)
    if output_params.json:
        api.cancel_json_output()

    # Prefix params
    prefix_params = getattr(api_ctx, "prefix_params", api_ctx)
    prefix_params.conda_prefix = context.conda_prefix
    prefix_params.root_prefix = context.root_prefix
    prefix_params.target_prefix = context.target_prefix

    # Networking params -- we always operate offline from libmamba's perspective
    remote_fetch_params = getattr(api_ctx, "remote_fetch_params", api_ctx)
    remote_fetch_params.user_agent = context.user_agent
    api_ctx.local_repodata_ttl = context.local_repodata_ttl
    api_ctx.offline = True
    api_ctx.use_index_cache = True

    # General params
    api_ctx.add_pip_as_python_dependency = context.add_pip_as_python_dependency
    api_ctx.always_yes = context.always_yes
    api_ctx.dry_run = context.dry_run
    api_ctx.envs_dirs = context.envs_dirs
    api_ctx.pkgs_dirs = context.pkgs_dirs
    api_ctx.use_lockfiles = False
    api_ctx.use_only_tar_bz2 = context.use_only_tar_bz2

    # Channels and platforms
    api_ctx.platform = context.subdir
    api_ctx.channels = context.channels
    api_ctx.channel_alias = str(_get_base_url(context.channel_alias.url(with_credentials=True)))

    RESERVED_NAMES = {"local", "defaults"}
    additional_custom_channels = {}
    for el in context.custom_channels:
        if context.custom_channels[el].canonical_name not in RESERVED_NAMES:
            additional_custom_channels[el] = _get_base_url(
                context.custom_channels[el].url(with_credentials=True), el
            )
    api_ctx.custom_channels = additional_custom_channels

    additional_custom_multichannels = {}
    for el in context.custom_multichannels:
        if el not in RESERVED_NAMES:
            additional_custom_multichannels[el] = []
            for c in context.custom_multichannels[el]:
                additional_custom_multichannels[el].append(
                    _get_base_url(c.url(with_credentials=True))
                )
    api_ctx.custom_multichannels = additional_custom_multichannels

    api_ctx.default_channels = [
        _get_base_url(x.url(with_credentials=True)) for x in context.default_channels
    ]

    if context.channel_priority is ChannelPriority.STRICT:
        api_ctx.channel_priority = api.ChannelPriority.kStrict
    elif context.channel_priority is ChannelPriority.FLEXIBLE:
        api_ctx.channel_priority = api.ChannelPriority.kFlexible
    elif context.channel_priority is ChannelPriority.DISABLED:
        api_ctx.channel_priority = api.ChannelPriority.kDisabled

    return api_ctx
