import json
import sys

from .common import _api
from .conda_interface import find_token, set_repo_token
from .utils import MirrorException, site_to_url


def get_repo_api(config):
    try:
        from repo_cli.utils.config import get_config

        r_config = get_config()
    except ImportError:
        raise MirrorException("Please install the 'conda-repo-cli' package.")
    sites = r_config.get("sites", {})
    ds = config.dest_site
    if not ds and not sites:
        raise MirrorException(
            "No repositories have been connected to conda-repo-cli. "
            "Please configure at least one repo before proceeding."
        )
    if not ds:
        ds = r_config.get("default_site")
    if not ds:
        ds = "default" if "default" in sites else next(iter(sites))
    if ds not in sites:
        # If dest_site is a valid domain name or URL, use that to
        # determine the API url of the site.
        url = site_to_url(ds, "api")
        if not url:
            raise MirrorException(
                "Site not found: %s.\n"
                "Please log in using conda-repo-cli or by supplying a token\n"
                "or username/password combination directly to anaconda-mirror." % ds
            )
        # See if it matches a pre-configured entry
        for k, v in sites.items():
            if v.get("url") == url:
                ds = k
                break
    if ds in sites:
        config.dest_site = ds
        url = sites[ds]["url"]
        if config.verify_ssl_dst and "ssl_verify" in sites[ds]:
            config.verify_ssl_dst = sites[ds]["ssl_verify"]
    if config.username and config.password:
        try:
            from repo_cli.utils.api import RepoApi
        except ImportError:
            raise MirrorException("Please install the 'conda-repo-cli' package.")
        t_api = RepoApi(url, verify_ssl=config.verify_ssl)
        t_api.login(config.username, config.password)
        config.password = t_api.get_user_token(force_scopes=None)
        config.username = None
    if config.password:
        set_repo_token(url, config.password)
        config.password = None
    repo_token = find_token(url)
    if not repo_token:
        url = "/".join(url.rsplit("/", 3)[:3])
        raise MirrorException(
            "Cannot authenticate to %s.\n"
            "Please log in using conda-repo-cli or by supplying a token\n"
            "or username/password combination directly to anaconda-mirror." % url
        )
    config.api_url = url
    config.dest_channel_alias = url + "/repo"
    config.api_headers = {"X-Auth": repo_token}
    result = {"auto_freeze": getattr(config, "auto_freeze", True)}
    return result


def _set_frozen(api, cname, frozen):
    if api["frozen"] != frozen and api["auto_freeze"]:
        data = {"indexing_behavior": "frozen" if frozen else "default"}
        _api("put", "channels", cname, json=data, throw=False)
        api["frozen"] = frozen


def begin_channel(api, cname, dry_run=False):
    response = _api("get", "channels", cname)
    fmode = response.get("indexing_behavior")
    if fmode is None:
        api["auto_freeze"] = False
    api["frozen"] = fmode == "frozen"
    if dry_run:
        return
    # Trigger an index generation
    _set_frozen(api, cname, False)
    if not api["frozen"]:
        _api("put", "channels", cname, "artifacts", "conda")


def patch_package(api, cname, platform, fn, metadata):
    _set_frozen(api, cname, True)
    rec = metadata.copy()
    rec["fn"] = fn
    data = {"repodata_record": json.dumps(rec)}
    _api("patch", "repo", cname, platform, fn, json=data)


def finish_channel(api, cname, dry_run):
    if dry_run:
        return
    _set_frozen(api, cname, False)
    # Trigger an index generation
    if not api["frozen"]:
        _api("put", "channels", cname, "artifacts", "conda")


def del_object(api, cname, platform, fn, metadata=None):
    _set_frozen(api, cname, False)
    record = {
        "action": "delete",
        "items": [
            {
                "name": metadata["name"],
                "family": "conda",
                "ckey": "%s/%s" % (platform, fn),
            }
        ],
    }
    _api("put", "channels", cname, "artifacts", "bulk", json=record, accept_404=True)


def put_object(api, cname, platform, fn, path_or_data=None, metadata=None):
    _set_frozen(api, cname, True)
    with open(path_or_data, "rb") as fp:
        multipart_form_data = {
            "content": (fn, fp),
            "filetype": (None, "conda1"),
            "size": (None, metadata["size"]),
            "repodata_record.json": (None, json.dumps(metadata)),
        }
        _api("post", "channels", cname, "artifacts", files=multipart_form_data)


def main():
    from .common import main as _main

    _main(sys.modules[__name__])
