import urllib.parse
import sys,os
import time
import shutil,time
import urllib.request
import zipfile,subprocess,json,base64
import tempfile
import platform


# from datetime import datetime

# with open("/tmp/python_start.log", "a") as f:
#     current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
#     f.write(f"Python script started at {current_time}!\n")
# 在你的 Python 部署脚本里加入这一行
# os.system("update-desktop-database ~/.local/share/applications/")
# ====================================================================
# 【外部固定值/全局变量管理区】
# 所有的配置和全局状态都以单独的常量形式定义，方便理解和修改。
# ====================================================================

# --- 状态标志 ---
exitflag = "" 

# --- 核心配置（用户要求不修改） ---
PROGRAM_NAME_PARAM = "program"
DEFAULT_SCRIPT_NAME = "open"
R34_PREFIX = "r34:"
DEFAULT_INPUT_STR = "r34:/home"

# --- 核心配置（用户要求提取的） ---
DOWNLOAD_AND_RUN_SCRIPT = "get_run"

# --- URL 和路径配置 ---
ONLINE_CODE_URL = "https://r34.cc/index.php/Qwadmin/Rwxy/echojson?type=json&conall=%3B%E6%95%B0%E6%8D%AE%E8%A1%A8%E5%90%8D%E7%AD%89%E4%BA%8Ebat_r34_cc%3B%E6%9F%A5%E7%9C%8B%E5%AF%86%E7%A0%81%E7%AD%89%E4%BA%8E8K3130517E"
SOFTWARE_BASE_URL = "https://pub.r34.cc/toolsoft/"
DEFAULT_SOFTWARE_DIR_D = "" #这里如果指定路径，那就会把文件安装到这里

# !!!--- 路径修改在这里 ---!!!
DEFAULT_SOFTWARE_DIR_RELATIVE = os.path.join("..", "toolsoft")
# !!!-----------------------!!!

# --- 临时文件配置 ---
TEMP_ZIP_NAME = "temp.zip"
TEMP_BAT_NAME_PREFIX = "temp."

# ====================================================================

from pathlib import Path

def start(url):
    """
    跨平台启动函数：支持 Windows (start), Linux (xdg-open), macOS (open)
    """
    print(f"正在处理路径/URL: {url}")
    
    # 统一路径分隔符 (仅在处理本地路径时有用)
    if os.path.exists(url):
        url = os.path.abspath(url)

    system = platform.system()
    
    # 1. 处理 Python 脚本的特殊逻辑
    if url.lower().endswith('.py'):
        python_exe = sys.executable
        if system == "Windows":
            # Windows: 使用 cmd /c 开启新窗口
            #cmd = f'start /wait "" cmd /c "{python_exe}" "{url}" & timeout /t 5'
            cmd = f'"{python_exe}" "{url}"'
            subprocess.call(cmd, shell=True)
        else:
            # Linux/macOS: 使用终端模拟器或直接后台运行
            # 这里尝试使用通用终端启动，如果失败则直接子进程运行
            print(f"正在 Unix 环境执行脚本...")
            subprocess.run([python_exe, url], check=True)
        return

    # 2. 处理普通文件或 URL 的打开
    try:
        if system == "Windows":
            os.startfile(url)
        elif system == "Darwin":  # macOS
            subprocess.call(["open", url])
        else:  # Linux 及其他
            subprocess.call(["xdg-open", url])
    except Exception as e:
        print(f"❌ 无法打开 {url}: {e}")

def start2(url):
    # 直接复用增强后的 start 函数
    start(url)


# 检测软件是否存在的函数
def check_software_exists(path):
    if os.path.exists(path):
        start(path)
        return True
    else:
        return False

# 检测软件是否存在的函数
def check_softwareurl_exists(url):
    # print("url: "+url) 
    try:
        response = urllib.request.urlopen(url)
        return True
    except urllib.error.HTTPError as e:
        return False


# 解压压缩包
def support_gbk(zip_file):
    """ 支持中文编码 """
    name_to_info = zip_file.NameToInfo
    # copy map first
    for name, info in name_to_info.copy().items():
        try:
            real_name = name.encode('cp437').decode('gbk')
        except:
            real_name = name
        if real_name != name:
            info.filename = real_name
            del name_to_info[name]
            name_to_info[real_name] = info
    return zip_file


def extract_compressed_file(file_path,extract_path):
    # 解压目标路径 
    # extract_path = os.path.dirname(file_path) 
    # 获取文件扩展名
    file_extension = os.path.splitext(file_path)[1].lower()
    # 根据文件扩展名选择解压方式
    if file_extension == '.zip':
        # 解压zip文件，支持中文编码
        with zipfile.ZipFile(file_path, 'r') as zfp:
            with support_gbk(zfp) as supported_zfp:
                supported_zfp.extractall(extract_path)
    # elif file_extension == '.rar': 
    #     # 解压rar文件，确保中文编码 
    #     import rarfile 
    #     with rarfile.RarFile(file_path, 'r') as rfp: 
    #         rfp.extractall(extract_path) 
    # elif file_extension == '.tar': 
    #     # 解压tar文件 
    #     with tarfile.open(file_path, 'r') as tfp: 
    #         tfp.extractall(extract_path) 
    # elif file_extension == '.gz': 
    #     # 解压gzip文件 
    #     extract_file = os.path.splitext(os.path.basename(file_path))[0] 
    #     with gzip.open(file_path, 'rb') as gfp: 
    #         with open(os.path.join(extract_path, extract_file), 'wb') as fp: 
    #             shutil.copyfileobj(gfp, fp) 
    else:
        raise ValueError("Unsupported file format")

# 下载并解压软件的函数
def download_and_extract_software(url, download_path, extract_path):
    # 下载软件zip文件
    urllib.request.urlretrieve(url, download_path)
    extract_compressed_file(download_path,extract_path)
    # 解压zip文件 
        
    # 返回解压后的软件目录路径
    return extract_path
    


def runconjb(content="",ex="bat"):
    # 使用常量
    bat_file = os.environ ['TEMP'] + "\\" + TEMP_BAT_NAME_PREFIX + ex
    if content=="":
        print("未接到参数。")
    else:
        # 将批处理程序内容写入文件
        with open(bat_file, 'wb') as f:
            f.write(content)
        # 运行批处理程序
        start(bat_file)  

# 恢复原始的默认参数
def getcodeandrun(argument,dataurl=ONLINE_CODE_URL):
   flag=False
   # 发送HTTP请求并获取响应
   try:
       response = urllib.request.urlopen(dataurl)
       
       data = response.read().decode('utf-8')
       json_data = json.loads(data)
    # 提取"arr"键值
       arr_data = json_data['arr']
       for item in arr_data:
          if item["功能名"]==argument:
             #print(item["codebs64"]) 
             if item.get("codebs64") is not None:
                content = base64.b64decode(item["codebs64"])
             elif item.get("code") is not None:
                content=item["code"]
                content=content.encode('utf-8')
             else:
                 return False
             # 使用 .get() 安全获取，并恢复原始默认值逻辑
             ex = item.get("ex", "bat")
             flag=True
             break    #跳出for
   except Exception as e:
       # 统一错误处理，兼容原版
       # print(f"错误: {e}") 
       return False
       
   if flag==True:
      runconjb(content,ex)
      print("正确运行脚本！")
      return True
   else:
      return False


# 恢复原始的默认参数 
def downsoftandrun(inputstr,softwaresite=SOFTWARE_BASE_URL,softwarepath=""):
    if inputstr=="":
        return False
    # 使用常量
    abpath=DEFAULT_SOFTWARE_DIR_D
    if os.path.exists(abpath):
        softwarepath=abpath
    else:
        # --- 路径逻辑调整：使用 os.path.join 配合 ..\\toolsoft\\ 确保指向上一级目录 ---
        script_dir = os.path.dirname(os.path.abspath(__file__))
        softwarepath = os.path.abspath(os.path.join(script_dir, DEFAULT_SOFTWARE_DIR_RELATIVE))
        # 为了确保它是一个目录，我们可以手动补一个系统分隔符
        softwarepath = os.path.join(softwarepath, "")
        #print(softwarepath)
        
        # 创建目录
        os.makedirs(softwarepath, exist_ok=True)

    # print(softwarepath) 
    # 使用常量
    softurlzip=softwaresite +urllib.parse.quote(inputstr) +".zip"
    software_download_path=softwarepath+TEMP_ZIP_NAME
    

    softurlexe=softwaresite +urllib.parse.quote(inputstr) +".exe"
    software_download_path_exe=softwarepath+inputstr+".exe"

    softurlpy=softwaresite +urllib.parse.quote(inputstr) +".py"
    software_download_path_py=softwarepath+inputstr+".py"

    software_extract_path=softwarepath+inputstr+"/"
    software_executable=software_extract_path+inputstr+".exe"
    software_executable2 = find_first_exe(software_extract_path)

    #文件是否存在，并保存temp.zip删除
    if os.path.exists(software_executable):
        start(software_executable)
        return True
    if os.path.exists(software_executable2):
        start(software_executable2)
        return True
    elif os.path.exists(software_download_path_exe):
        start(software_download_path_exe)
        return True
    elif os.path.exists(software_download_path_py):
        start(software_download_path_py)
        return True
    elif check_softwareurl_exists(softurlexe):
    # 下载软件exe文件
        urllib.request.urlretrieve(softurlexe, software_download_path_exe)
        start(software_download_path_exe)
        return True
    elif check_softwareurl_exists(softurlpy):
    # 下载软件exe文件
        urllib.request.urlretrieve(softurlpy, software_download_path_py)
        start(software_download_path_py)
        return True
    elif check_softwareurl_exists(softurlzip):
        print(softurlzip)
       
        software_path = download_and_extract_software(softurlzip, software_download_path, software_extract_path)
        exe_path = find_first_exe(software_extract_path)
        # print(software_path) 
        # time.sleep(5000) 
        if os.path.exists(software_executable):
            start(software_executable)
        elif os.path.exists(exe_path):
            start(exe_path)
        else:
            return False
        return True

    else:
        # print("网上找不到exe的url") 
        return False
# import os 

def find_first_exe(directory):
    # 定义支持的扩展名集合
    valid_extensions = {'.exe', '.py', '.bat', '.ahk'}
    
    for root, dirs, files in os.walk(directory):
        for file in files:
            # 获取文件扩展名（小写）
            ext = os.path.splitext(file)[1].lower()
            # 检查是否在支持的扩展名中
            if ext in valid_extensions:

                return os.path.join(root, file)
    return ''


def parse_inputfile(inputfile: str) -> dict:
    # 初始化结果
    result = {"script": DEFAULT_SCRIPT_NAME, "params": {"path": inputfile}} # 使用常量
    
    # 处理空字符串
    if not inputfile:
        return result
    
    # 取前10个字符（若不足10则取全部）
    check_str = inputfile[:10]
    
    # 如果前10个字符无 '?'，直接返回默认结果
    if '?' not in check_str:
        return result
    
    # 分割第一个 '?'
    parts = inputfile.split('?', 1)
    # 使用常量
    script = parts[0] if parts[0] else DEFAULT_SCRIPT_NAME
    param_str = parts[1] if len(parts) > 1 else ""
    
    # 更新脚本名
    result["script"] = script
    
    # 解析参数
    if not param_str:
        # 如果参数为空，设置 params = {"path": script}
        result["params"] = {"path": script}
    else:
        # 以 '&' 分割参数
        params = {}
        for param in param_str.split('&'):
            if not param:  # 忽略空参数
                continue
            # 分割 key=value
            if '=' in param:
                key, value = param.split('=', 1)
                if key:  # 确保 key 不为空
                    params[key] = value
            else:
                params[param] = ""  # 无 '='，值设为空
        # 如果解析后 params 为空，设置默认 path
        result["params"] = params if params else {"path": script}
    
    return result

def process_script(jbscript: str, paramarr: dict) -> bool:
    """
    处理脚本逻辑，带错误处理。
    Args:
        jbscript: 脚本名（字符串）
        paramarr: 参数字典
    Returns:
        bool: True 表示成功，False 表示失败
    """
    try:
        # 检查输入类型
        if not isinstance(jbscript, str):
            print(f"错误: 无效的脚本名类型，期望字符串，得到 {type(jbscript)}")
            return False
        
        if not isinstance(paramarr, dict):
            print(f"错误: 无效的参数类型，期望字典，得到 {type(paramarr)}")
            return False
        
        # 处理 "下载并运行程序"
        if jbscript == DOWNLOAD_AND_RUN_SCRIPT: # 使用常量
            # 检查program是否存在
            if PROGRAM_NAME_PARAM not in paramarr: # 使用常量
                print(f"错误: 参数中缺少 '{PROGRAM_NAME_PARAM}'") # 使用常量
                return False
            
            jb = paramarr[PROGRAM_NAME_PARAM] # 使用常量
            
            # 调用 getcodeandrun
            try:
                if getcodeandrun(jb):
                    print("成功: 代码运行完成")
                    return True
                else:
                    print("2.代码数据库中找不到相应的代码！")
            except Exception as e:
                print(f"错误: getcodeandrun 失败 - {str(e)}")
            
            # 调用 downsoftandrun
            try:
                if downsoftandrun(jb):
                    print("成功: 软件下载并运行")
                    return True
                else:
                    print("3.并不是线上软件！")
                    return False
            except Exception as e:
                print(f"错误: downsoftandrun 失败 - {str(e)}")
                return False
        else:
            print("0.index 提前处理失败")
            return False
    
    except Exception as e:
        print(f"错误: 未知异常 - {str(e)}")
        return False
# ----------------以上是代码区，在线处理文件下载用的--------------------------

#无参数时的出错处理
if len(sys.argv) >=2:
   inputstr=sys.argv[1]
else:
   inputstr=DEFAULT_INPUT_STR # 使用常量
   # 恢复原始的示例代码
   # inputstr="r34:notepad.exe"
   # inputstr="r34:get_run?program=cpuz"
   # inputstr="r34:%E4%B8%8B%E8%BD%BD%E5%B9%B6%E8%BF%90%E8%A1%8C%E7%A8%8B%E5%BA%8F?%E7%A8%8B%E5%BA%8F%E5%90%8D=cpuz"
   # inputstr="r34:get_run?program=ipconfig"
   # inputstr="r34:get_run?program=pdfremovewater_apipy"
   inputstr="r34:/home"
#去除cmd:这几个字
input1=inputstr[len(R34_PREFIX):] # 使用常量
#input1=input1.replace("/","\\") 
print(input1)
inputfile=urllib.parse.unquote(input1)
realfolderpath=""
(filename, extension) = os.path.splitext(inputfile)
#处理没有后缀的情况
if len(extension) < 1:
   if inputfile[-1:] =="\\":
      inputfile=inputfile[:-1]
   #print("inputfile1:"+ inputfile) 
   #time.sleep(3) 
   #这里处理文件夹， 

result = parse_inputfile(inputfile)
jbscript=result["script"]
paramarr=result["params"]
print("jbscript: "+jbscript)
print(paramarr)



#处理文件，指没有\的情况
# print("处理文件，指没有\的情况") 
# startstr(inputfile) 

if exitflag == "true": # 使用全局变量
   print("不执行")
   sys.exit()

#time.sleep(5) 
#(filename, extension) = os.path.splitext(inputfile) 
#wholepath=os.path.expandvars(inputfile) 
#jb=inputfile 
#print(inputfile[0:3]) 

# --- 在脚本逻辑开始前定义标记 ---
has_executed = False 

# ====================================================================
# 0. 执行顺序：处理 index 逻辑
# ====================================================================
if not has_executed:
    if jbscript == "index":
        # 注意：Linux/macOS 下没有 notepad，这里使用了之前定义的跨平台 start 函数
        index_file = os.path.expanduser(r'~/Desktop/index/index.html')
        if os.path.exists(index_file):
            print(f"正在打开 Index 页面: {index_file}")
            start(index_file) # 使用 start 替代 subprocess.call(['notepad',...]) 以兼容跨平台
            has_executed = True
    #     else:
    #         print(f"1. 找不到 index 文件: {index_file}")
    # else:
    #     print("1. 不是 index 模式")

# ====================================================================
# 1. 执行顺序：处理本地文件或目录
# ====================================================================
if not has_executed:
    try:
        if jbscript == DEFAULT_SCRIPT_NAME:
            path = paramarr.get("path", "")
            wholepath = os.path.expandvars(path)
            if path and os.path.exists(wholepath):
                print("是有效的本地文件或目录！")
                start(wholepath)
                has_executed = True
            else:
                print("1. 本地路径不存在")
    except Exception as e:
        print(f"错误: 本地文件处理失败 - {str(e)}")

# ====================================================================
# 2. 执行顺序：下载并运行程序 (优先级高)
# ====================================================================
if not has_executed:
    try:
        if jbscript == DOWNLOAD_AND_RUN_SCRIPT:
            jb = paramarr.get(PROGRAM_NAME_PARAM, "")
            # 尝试执行线上代码
            if jb and getcodeandrun(jb):
                print("成功: 代码运行完成")
                has_executed = True 
            
            # 如果代码没跑通，尝试下载软件
            if not has_executed and jb and downsoftandrun(jb):
                print("成功: 软件下载并运行")
                has_executed = True
                
            if not has_executed:
                print("2/3. 线上数据库和软件库均未匹配")
    except Exception as e:
        print(f"错误: {DOWNLOAD_AND_RUN_SCRIPT} 过程失败 - {str(e)}")


# ====================================================================
# 3. 执行顺序：最后的兜底尝试
# ====================================================================
if not has_executed:
    try:
        if jbscript == DEFAULT_SCRIPT_NAME:
            path = paramarr.get("path", "")
            if path:
                start(path)
                print("4. 已尝试直接运行原始字符串：" + path)
                has_executed = True
    except Exception as e:
        print(f"错误: 兜底运行失败 - {str(e)}")

# ====================================================================
# 最后部分：统一退出处理
# ====================================================================
print("------------------------------------------------------------------------")
if has_executed:
    print("流程控制：任务已成功执行，准备退出。")
else:
    print("流程控制：未匹配到任何可执行任务。")

print("------------------------------------------------------------------------")

time.sleep(5)
sys.exit(0)
