"""Mirror configuration CLI for domestic acceleration."""

from __future__ import annotations

import json
import os
import subprocess
import sys
from pathlib import Path
from typing import Literal


def get_all_mirrors() -> dict:
    """Get all available mirrors with their configurations."""
    from multi_lang_build.mirror.config import MIRROR_CONFIGS

    mirrors = {}
    for key, config in MIRROR_CONFIGS.items():
        mirrors[key] = {
            "name": config["name"],
            "url": config["url"],
        }
    return mirrors


def print_mirrors() -> None:
    """Print all available mirrors."""
    mirrors = get_all_mirrors()

    print("\n📦 Available Mirrors:")
    print("-" * 60)

    # Group by category
    categories = {
        "js": ["npm", "pnpm", "yarn"],
        "go": ["go", "go_qiniu", "go_vip"],
        "python": ["pip", "pip_aliyun", "pip_douban", "pip_huawei", "python", "poetry"],
    }

    category_names = {
        "js": "🌐 JavaScript (npm/pnpm/yarn)",
        "go": "🔷 Go",
        "python": "🐍 Python (pip/PyPI)",
    }

    for cat_key, cat_mirrors in categories.items():
        print(f"\n{category_names.get(cat_key, cat_key)}")
        for mirror_key in cat_mirrors:
            if mirror_key in mirrors:
                config = mirrors[mirror_key]
                print(f"  • {mirror_key:12} - {config['name']}")
                print(f"               {config['url']}")

    print()


def configure_pip(mirror_key: str) -> bool:
    """Configure pip mirror using pip config command."""
    from multi_lang_build.mirror.config import get_mirror_config

    config = get_mirror_config(mirror_key)
    if config is None:
        print(f"❌ Unknown pip mirror: {mirror_key}")
        return False

    url = config["url"]
    if not url.endswith("/simple") and not url.endswith("/simple/"):
        url = f"{url}/simple"

    # Try pip3 first, fallback to pip
    pip_cmd = "pip3" if sys.platform != "win32" else "pip"

    try:
        subprocess.run(
            [pip_cmd, "config", "set", "global.index-url", url],
            check=True,
        )
        print(f"✅ pip mirror set to: {url}")
        return True
    except subprocess.CalledProcessError as e:
        print(f"❌ Failed to set pip mirror: {e}")
        return False
    except FileNotFoundError:
        # Try alternative
        try:
            alternative = "pip" if pip_cmd == "pip3" else "pip3"
            subprocess.run(
                [alternative, "config", "set", "global.index-url", url],
                check=True,
            )
            print(f"✅ pip mirror set to: {url}")
            return True
        except Exception:
            print("❌ pip/pip3 not found")
            return False


def configure_go(mirror_key: str) -> bool:
    """Configure Go proxy using go env -w."""
    from multi_lang_build.mirror.config import get_mirror_config

    config = get_mirror_config(mirror_key)
    if config is None:
        print(f"❌ Unknown Go mirror: {mirror_key}")
        return False

    # Get the GOPROXY value from environment variables
    proxy_value = config["environment_variables"].get("GOPROXY", f"{config['url']},direct")

    try:
        subprocess.run(
            ["go", "env", "-w", f"GOPROXY={proxy_value}"],
            check=True,
        )
        print(f"✅ Go GOPROXY set to: {proxy_value}")

        # Also set GOSUMDB if present
        gosumdb = config["environment_variables"].get("GOSUMDB")
        if gosumdb:
            subprocess.run(
                ["go", "env", "-w", f"GOSUMDB={gosumdb}"],
                check=True,
            )
            print(f"✅ Go GOSUMDB set to: {gosumdb}")

        return True
    except subprocess.CalledProcessError as e:
        print(f"❌ Failed to set Go mirror: {e}")
        return False
    except FileNotFoundError:
        print("❌ go not found")
        return False


def configure_npm(mirror_key: str) -> bool:
    """Configure npm/pnpm registry."""
    from multi_lang_build.mirror.config import get_mirror_config

    config = get_mirror_config(mirror_key)
    if config is None:
        print(f"❌ Unknown npm mirror: {mirror_key}")
        return False

    url = config["url"]

    try:
        subprocess.run(
            ["npm", "config", "set", "registry", url],
            check=True,
        )
        print(f"✅ npm registry set to: {url}")

        # Also set for pnpm if available
        try:
            subprocess.run(
                ["pnpm", "config", "set", "registry", url],
                check=True,
            )
            print(f"✅ pnpm registry set to: {url}")
        except (subprocess.CalledProcessError, FileNotFoundError):
            pass

        return True
    except subprocess.CalledProcessError as e:
        print(f"❌ Failed to set npm registry: {e}")
        return False
    except FileNotFoundError:
        print("❌ npm not found")
        return False


def get_current_config() -> dict:
    """Get current mirror configuration."""
    config = {}

    # Try pip3 first, fallback to pip
    pip_cmd = "pip3" if sys.platform != "win32" else "pip"

    try:
        result = subprocess.run(
            [pip_cmd, "config", "get", "global.index-url"],
            capture_output=True,
            text=True,
        )
        if result.returncode == 0 and result.stdout.strip():
            config["pip"] = result.stdout.strip()
    except Exception:
        pass

    # Check Go
    try:
        result = subprocess.run(
            ["go", "env", "GOPROXY"],
            capture_output=True,
            text=True,
        )
        if result.returncode == 0:
            config["go"] = result.stdout.strip()
    except Exception:
        pass

    # Check npm
    try:
        result = subprocess.run(
            ["npm", "config", "get", "registry"],
            capture_output=True,
            text=True,
        )
        if result.returncode == 0:
            config["npm"] = result.stdout.strip()
    except Exception:
        pass

    return config


def configure_mirror(mirror_type: str, mirror_key: str) -> bool:
    """Configure mirror for a specific package manager.

    Args:
        mirror_type: Package manager type (pip, go, npm)
        mirror_key: Mirror key to use

    Returns:
        True if successful, False otherwise
    """
    if mirror_type == "pip":
        return configure_pip(mirror_key)
    elif mirror_type == "go":
        return configure_go(mirror_key)
    elif mirror_type in ["npm", "pnpm"]:
        return configure_npm(mirror_key)
    else:
        print(f"❌ Unknown package manager: {mirror_type}")
        return False


def mirror_main():
    """Main entry point for mirror command."""
    import argparse

    parser = argparse.ArgumentParser(
        description="Configure domestic mirror acceleration",
        epilog="""
Examples:
  %(prog)s list                    List all available mirrors
  %(prog)s set pip                 Configure pip mirror (default)
  %(prog)s set go                  Configure Go proxy
  %(prog)s set npm                 Configure npm registry
  %(prog)s show                    Show current configuration
        """,
    )
    parser.add_argument(
        "--version",
        action="version",
        version="%(prog)s 0.2.2",
    )

    subparsers = parser.add_subparsers(dest="command", help="Commands")

    # list command
    list_parser = subparsers.add_parser("list", help="List available mirrors")
    list_parser.add_argument(
        "--json",
        action="store_true",
        help="Output as JSON",
    )
    list_parser.add_argument(
        "--type",
        type=str,
        choices=["pip", "go", "npm"],
        help="Filter by type",
    )

    # set command
    set_parser = subparsers.add_parser("set", help="Configure mirror")
    set_parser.add_argument(
        "type",
        type=str,
        default="pip",
        nargs="?",
        choices=["pip", "go", "npm", "pnpm"],
        help="Package manager type (default: pip)",
    )
    set_parser.add_argument(
        "mirror",
        type=str,
        nargs="?",
        default="pip",
        help="Mirror to use",
    )

    # show command
    show_parser = subparsers.add_parser("show", help="Show current mirror configuration")

    args = parser.parse_args()

    if args.command == "list":
        mirrors = get_all_mirrors()
        if getattr(args, "json", False):
            print(json.dumps(mirrors, indent=2, ensure_ascii=False))
        else:
            print_mirrors()

    elif args.command == "set":
        mirror_type = args.type
        mirror_key = args.mirror
        success = configure_mirror(mirror_type, mirror_key)
        sys.exit(0 if success else 1)

    elif args.command == "show":
        config = get_current_config()
        if config:
            print("\n📦 Current Mirror Configuration:")
            print("-" * 40)
            for key, value in config.items():
                print(f"  • {key}: {value}")
            print()
        else:
            print("\n📦 No mirror configured")
            print("   Run 'multi-lang-build mirror set <type> <mirror>' to configure")
            print()
            print_mirrors()

    else:
        # No subcommand, show help
        parser.print_help()
        print("\n📋 Commands:")
        print("  list              List all available mirrors")
        print("  set <type> <name> Configure mirror (type: pip/go/npm)")
        print("  show              Show current configuration")
        print("\n📋 Examples:")
        print("  multi-lang-build mirror list")
        print("  multi-lang-build mirror set pip")
        print("  multi-lang-build mirror set go")
        print("  multi-lang-build mirror set npm")


if __name__ == "__main__":
    mirror_main()
