"""Command-line interface for condasetup."""

from __future__ import annotations

import argparse
import logging
import subprocess
from pathlib import Path
from typing import Final

logging.basicConfig(level=logging.INFO, format="%(message)s")
logger = logging.getLogger(__name__)

# Conda mirror URLs
_CONDA_MIRROR_URLS: Final[dict[str, frozenset[str]]] = {
    "tsinghua": frozenset(
        [
            "https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/",
            "https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/",
            "https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r/",
            "https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2/",
            "https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/pro/",
            "https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/",
            "https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/bioconda/",
            "https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/menpo/",
            "https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/",
        ]
    ),
    "ustc": frozenset(
        [
            "https://mirrors.ustc.edu.cn/anaconda/pkgs/main/",
            "https://mirrors.ustc.edu.cn/anaconda/pkgs/free/",
            "https://mirrors.ustc.edu.cn/anaconda/pkgs/r/",
            "https://mirrors.ustc.edu.cn/anaconda/pkgs/msys2/",
            "https://mirrors.ustc.edu.cn/anaconda/pkgs/pro/",
            "https://mirrors.ustc.edu.cn/anaconda/pkgs/dev/",
            "https://mirrors.ustc.edu.cn/anaconda/cloud/conda-forge/",
            "https://mirrors.ustc.edu.cn/anaconda/cloud/bioconda/",
            "https://mirrors.ustc.edu.cn/anaconda/cloud/menpo/",
            "https://mirrors.ustc.edu.cn/anaconda/cloud/pytorch/",
        ]
    ),
    "bsfu": frozenset(
        [
            "https://mirrors.bsfu.edu.cn/anaconda/pkgs/main/",
            "https://mirrors.bsfu.edu.cn/anaconda/pkgs/free/",
            "https://mirrors.bsfu.edu.cn/anaconda/pkgs/r/",
            "https://mirrors.bsfu.edu.cn/anaconda/pkgs/msys2/",
            "https://mirrors.bsfu.edu.cn/anaconda/pkgs/pro/",
            "https://mirrors.bsfu.edu.cn/anaconda/pkgs/dev/",
            "https://mirrors.bsfu.edu.cn/anaconda/cloud/conda-forge/",
            "https://mirrors.bsfu.edu.cn/anaconda/cloud/bioconda/",
            "https://mirrors.bsfu.edu.cn/anaconda/cloud/menpo/",
            "https://mirrors.bsfu.edu.cn/anaconda/cloud/pytorch/",
        ]
    ),
    "aliyun": frozenset(
        [
            "https://mirrors.aliyun.com/anaconda/pkgs/main/",
            "https://mirrors.aliyun.com/anaconda/pkgs/free/",
            "https://mirrors.aliyun.com/anaconda/pkgs/r/",
            "https://mirrors.aliyun.com/anaconda/pkgs/msys2/",
            "https://mirrors.aliyun.com/anaconda/pkgs/pro/",
            "https://mirrors.aliyun.com/anaconda/pkgs/dev/",
            "https://mirrors.aliyun.com/anaconda/cloud/conda-forge/",
            "https://mirrors.aliyun.com/anaconda/cloud/bioconda/",
            "https://mirrors.aliyun.com/anaconda/cloud/menpo/",
            "https://mirrors.aliyun.com/anaconda/cloud/pytorch/",
        ]
    ),
}


def _backup_condarc() -> bool:
    """Backup existing .condarc file with version control.

    Returns
    -------
        True if backup successful or no file to backup, False on failure
    """
    old_config = Path.home() / ".condarc"
    backup_base = Path.home() / ".condarc.bak"

    if not old_config.exists():
        logger.debug("No existing .condarc file found")
        return True

    # If backup already exists, create numbered version to avoid overwriting
    backup_version = backup_base
    counter = 1
    while backup_version.exists():
        backup_version = Path.home() / f".condarc.bak.{counter}"
        counter += 1

    try:
        old_config.rename(backup_version)
    except OSError:
        logger.exception("Failed to backup .condarc")
        return False
    else:
        logger.info(f"Backed up .condarc to {backup_version.name}")
        return True


def set_conda_mirror(mirror: str = "tsinghua") -> None:
    """Set the Conda mirror for the given channel.

    Args:
        mirror: Mirror name (tsinghua, ustc, bsfu, or aliyun)
    """
    if mirror not in _CONDA_MIRROR_URLS:
        logger.error(f"Invalid mirror: {mirror}")
        return

    # Backup existing configuration
    if not _backup_condarc():
        logger.error("Backup failed, aborting mirror setup")
        return

    mirror_urls = _CONDA_MIRROR_URLS[mirror]
    for url in mirror_urls:
        logger.debug(f"Adding mirror: {url}")
        try:
            subprocess.run(["conda", "config", "--add", "channels", url], check=True)
        except subprocess.CalledProcessError:
            logger.exception(f"Failed to add mirror {url}")
            return
    try:
        subprocess.run(
            ["conda", "config", "--set", "show_channel_urls", "yes"],
            check=True,
        )
        logger.info("Conda mirror set successfully")
    except subprocess.CalledProcessError:
        logger.exception("Failed to set show_channel_urls")


def parse_args() -> argparse.Namespace:
    """Parse command line arguments.

    Returns
    -------
        Parsed arguments
    """
    parser = argparse.ArgumentParser(description="Set up Conda environment")
    parser.add_argument(
        "mirror",
        type=str,
        choices=["tsinghua", "ustc", "bsfu", "aliyun"],
        nargs="?",
        default="tsinghua",
        help="Conda mirror to use",
    )
    parser.add_argument("-d", "--debug", help="Debug mode", action="store_true")

    return parser.parse_args()


def main() -> None:
    """Run main entry point for condasetup CLI."""
    args = parse_args()

    if args.debug:
        logger.setLevel(logging.DEBUG)

    set_conda_mirror(args.mirror)


if __name__ == "__main__":
    main()
