import os
import platform
import requests
import gzip
import shutil
from zipfile import ZipFile
import stat
import argparse
import subprocess
import tempfile

# 定义常量
MIHOMO_BASE_URL = 'https://github.com/MetaCubeX/mihomo/releases/download'
CORE_SERVICE_BASE_URL = 'https://github.com/alroyso/core-service/releases/download'
MIHOMO_VERSION = 'v1.18.8'  # 根据实际版本修改
CORE_SERVICE_VERSION = 'v1.0.2'
ASSETS_DIR = './assets/bin'
SYSTEM = platform.system().lower()

# ClashName.platform 和 ClashName.arch 是动态生成的
def get_platform_arch():
    return SYSTEM, platform.machine()

# 如果目录不存在，创建下载目录
if not os.path.exists(ASSETS_DIR):
    os.makedirs(ASSETS_DIR)

def get_download_urls():
    """
    根据系统生成 mihomo 和 core-service 的下载链接，分别下载 arm64 和 x86_64 架构
    """
    download_urls = []

    # 获取 ClashName 的 platform 和 arch
    platform_name, arch_name = get_platform_arch()

    # 下载 macOS、Linux、Windows 的 arm64 和 x86_64 架构
    if SYSTEM == 'darwin':
        # macOS
        download_urls.append((
            f'mihomo-darwin-arm64-{MIHOMO_VERSION}.gz',
            f'{MIHOMO_BASE_URL}/{MIHOMO_VERSION}/mihomo-darwin-arm64-{MIHOMO_VERSION}.gz',
            'arm64'
        ))
        download_urls.append((
            f'mihomo-darwin-amd64-{MIHOMO_VERSION}.gz',
            f'{MIHOMO_BASE_URL}/{MIHOMO_VERSION}/mihomo-darwin-amd64-{MIHOMO_VERSION}.gz',
            'x86_64'
        ))
        download_urls.append((
            f'ccore-service-darwin-arm64-{CORE_SERVICE_VERSION}.gz',
            f'{CORE_SERVICE_BASE_URL}/{CORE_SERVICE_VERSION}/ccore-service-darwin-arm64-{CORE_SERVICE_VERSION}.gz',
            'arm64'
        ))
        download_urls.append((
            f'ccore-service-darwin-amd64-{CORE_SERVICE_VERSION}.gz',
            f'{CORE_SERVICE_BASE_URL}/{CORE_SERVICE_VERSION}/ccore-service-darwin-amd64-{CORE_SERVICE_VERSION}.gz',
            'x86_64'
        ))
    elif SYSTEM == 'linux':
        # Linux
        download_urls.append((
            f'mihomo-linux-arm64-{MIHOMO_VERSION}.gz',
            f'{MIHOMO_BASE_URL}/{MIHOMO_VERSION}/mihomo-linux-arm64-{MIHOMO_VERSION}.gz',
            'arm64'
        ))
        download_urls.append((
            f'mihomo-linux-amd64-{MIHOMO_VERSION}.gz',
            f'{MIHOMO_BASE_URL}/{MIHOMO_VERSION}/mihomo-linux-amd64-{MIHOMO_VERSION}.gz',
            'x86_64'
        ))
        download_urls.append((
            f'ccore-service-linux-arm64-{CORE_SERVICE_VERSION}.gz',
            f'{CORE_SERVICE_BASE_URL}/{CORE_SERVICE_VERSION}/ccore-service-linux-arm64-{CORE_SERVICE_VERSION}.gz',
            'arm64'
        ))
        download_urls.append((
            f'ccore-service-linux-amd64-{CORE_SERVICE_VERSION}.gz',
            f'{CORE_SERVICE_BASE_URL}/{CORE_SERVICE_VERSION}/ccore-service-linux-amd64-{CORE_SERVICE_VERSION}.gz',
            'x86_64'
        ))
    elif SYSTEM == 'windows':
        # Windows
        download_urls.append((
            f'mihomo-windows-arm64-{MIHOMO_VERSION}.zip',
            f'{MIHOMO_BASE_URL}/{MIHOMO_VERSION}/mihomo-windows-arm64-{MIHOMO_VERSION}.zip',
            'arm64'
        ))
        download_urls.append((
            f'mihomo-windows-amd64-{MIHOMO_VERSION}.zip',
            f'{MIHOMO_BASE_URL}/{MIHOMO_VERSION}/mihomo-windows-amd64-{MIHOMO_VERSION}.zip',
            'x86_64'
        ))
        download_urls.append((
            f'ccore-service-windows-arm64-{CORE_SERVICE_VERSION}.zip',
            f'{CORE_SERVICE_BASE_URL}/{CORE_SERVICE_VERSION}/ccore-service-windows-arm64-{CORE_SERVICE_VERSION}.zip',
            'arm64'
        ))
        download_urls.append((
            f'ccore-service-windows-amd64-{CORE_SERVICE_VERSION}.zip',
            f'{CORE_SERVICE_BASE_URL}/{CORE_SERVICE_VERSION}/ccore-service-windows-amd64-{CORE_SERVICE_VERSION}.zip',
            'x86_64'
        ))

    return download_urls

def download_file(url, output_path):
    """
    下载文件
    """
    print(f"正在下载 {url} ...")
    response = requests.get(url, stream=True)
    if response.status_code == 200:
        with open(output_path, 'wb') as file:
            shutil.copyfileobj(response.raw, file)
        print(f"下载完成: {output_path}")
    else:
        print(f"下载失败 {url}, 状态码: {response.status_code}")

def extract_gz_file(file_path, output_path):
    """
    解压 .gz 文件
    """
    print(f"正在解压 {file_path} ...")
    with gzip.open(file_path, 'rb') as f_in:
        with open(output_path, 'wb') as f_out:
            shutil.copyfileobj(f_in, f_out)
    print(f"解压到 {output_path}")

def extract_zip_file(file_path, output_dir):
    """
    解压 .zip 文件
    """
    print(f"正在解压 {file_path} ...")
    with ZipFile(file_path, 'r') as zip_ref:
        zip_ref.extractall(output_dir)
    print(f"解压到 {output_dir}")

def merge_binaries(arm_file, x86_file, output_file):
    """
    使用 lipo 合并 arm64 和 x86_64 的二进制文件
    """
    print(f"正在合并 {arm_file} 和 {x86_file} 到 {output_file}")
    subprocess.run(['lipo', '-create', '-output', output_file, arm_file, x86_file], check=True)
    print(f"成功合并到 {output_file}")

def add_executable_permission(file_path):
    """
    添加可执行权限（适用于 macOS 和 Linux）
    """
    print(f"正在添加可执行权限到 {file_path}")
    st = os.stat(file_path)
    os.chmod(file_path, st.st_mode | stat.S_IEXEC)
    print(f"已添加可执行权限到 {file_path}")

def rename_file(original_path, new_name):
    """
    重命名文件
    """
    new_path = os.path.join(ASSETS_DIR, new_name)
    shutil.move(original_path, new_path)
    print(f"已重命名 {original_path} 为 {new_path}")
    return new_path

def main():
    # 获取下载链接和文件名
    download_urls = get_download_urls()

    # 创建临时目录
    with tempfile.TemporaryDirectory() as temp_dir:
        # 存储架构对应的下载路径（仅适用于 macOS 合并）
        downloads = {
            'mihomo': {'arm64': '', 'x86_64': ''},
            'core-service': {'arm64': '', 'x86_64': ''}
        }

        for file_name, url, arch in download_urls:
            # 下载文件
            download_path = os.path.join(temp_dir, file_name)
            download_file(url, download_path)

            # 确定服务名称
            if 'core-service' in file_name:
                service_name = 'core-service'
            elif 'mihomo' in file_name:
                service_name = 'mihomo'
            else:
                raise ValueError(f"未知的服务名称: {file_name}")

            # 构建输出路径
            output_file = os.path.join(temp_dir, service_name + '-' + arch)

            # 解压文件
            if file_name.endswith('.gz'):
                extract_gz_file(download_path, output_file)
            elif file_name.endswith('.zip'):
                extract_zip_file(download_path, temp_dir)

            # 如果是 macOS，记录不同架构的文件路径
            if SYSTEM == 'darwin':
                downloads[service_name][arch] = output_file

        # 合并 macOS 下的二进制文件或直接重命名
        if SYSTEM == 'darwin':
            for service in ['mihomo', 'core-service']:
                arm_file = downloads[service]['arm64']
                x86_file = downloads[service]['x86_64']
                if arm_file and x86_file:
                    merged_output = os.path.join(temp_dir, service)
                    merge_binaries(arm_file, x86_file, merged_output)
                    add_executable_permission(merged_output)
                    
                    # 如果是合并改名,core-{SYSTEM}
                    # service-{SYSTEM}
                    # 其他平台不变
                    new_name = f"core-{SYSTEM}" if service == 'mihomo' else f"service-{SYSTEM}"
                    rename_file(merged_output, new_name)
        else:
            # 对于 Linux 和 Windows，直接重命名最新下载的文件
            for service in ['mihomo', 'core-service']:
                latest_file = max(
                    [f for f in os.listdir(temp_dir) if service in f],
                    key=lambda x: os.path.getmtime(os.path.join(temp_dir, x))
                )
                new_name = f"core-{SYSTEM}-{platform.machine()}" if service == 'mihomo' else f"service-{SYSTEM}-{platform.machine()}"
                if SYSTEM == 'windows':
                    new_name += '.exe'
                rename_file(os.path.join(temp_dir, latest_file), new_name)
                if SYSTEM == 'linux':
                    add_executable_permission(os.path.join(ASSETS_DIR, new_name))

if __name__ == "__main__":
    main()