#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
闲闲SDK混淆工具 - 命令行接口
单独的CLI工具，不影响原有的oc_start.py
"""

from ObjectiveC.oc_custom.custom_pbxproj_clean import DemoProjectCleanerSafe
from ObjectiveC.oc_custom.custom_pbxproj_add import SmartSDKAdder
from ObjectiveC.oc_custom import custom_h_search_file_content_message
from ObjectiveC.oc_custom import custom_util
from ObjectiveC.oc_custom import custom_end
from ObjectiveC.oc_custom import custom_start
from ObjectiveC.oc_custom import custom_get_params
from ObjectiveC.oc_custom import custom_a_framework
from ObjectiveC import oc_tool
from ObjectiveC import oc_yaml
from ObjectiveC import oc_util
import os
import time
import sys
import argparse

# 添加当前目录到Python路径，以支持从项目根目录运行
current_dir = os.path.dirname(os.path.abspath(__file__))
if current_dir not in sys.path:
    sys.path.insert(0, current_dir)

# 基础模块导入

# 功能模块导入（延迟导入以避免启动时的导入错误）


def import_function_modules():
    """延迟导入功能模块"""
    global project, c_folder, d_string, e_print_annotation, f_file, g_notification
    global i_property, j_enum, k_block, l_constant, m_delegate, n_method, n_c_method
    global o_image, p_uuid, q_location, s_string, t_host, v_local_variable, u_class

    try:
        from ObjectiveC.oc_function import b_project as project
        from ObjectiveC.oc_function import c_folder
        from ObjectiveC.oc_function import d_string
        from ObjectiveC.oc_function import e_print_annotation
        from ObjectiveC.oc_function import f_file
        from ObjectiveC.oc_function import g_notification
        from ObjectiveC.oc_function import i_property
        from ObjectiveC.oc_function import j_enum
        from ObjectiveC.oc_function import k_block
        from ObjectiveC.oc_function import l_constant
        from ObjectiveC.oc_function import m_delegate
        from ObjectiveC.oc_function import n_method
        from ObjectiveC.oc_function import n_c_method
        from ObjectiveC.oc_function import o_image
        from ObjectiveC.oc_function import p_uuid
        from ObjectiveC.oc_function import q_location
        from ObjectiveC.oc_function import s_string
        from ObjectiveC.oc_function import t_host
        from ObjectiveC.oc_function import v_local_variable
        from ObjectiveC.oc_function import u_class
        return True
    except ImportError as e:
        print(f"警告: 功能模块导入失败: {e}")
        return False


# 全局变量，用于存储导入的模块
project = None
c_folder = None
d_string = None
e_print_annotation = None
f_file = None
g_notification = None
i_property = None
j_enum = None
k_block = None
l_constant = None
m_delegate = None
n_method = None
n_c_method = None
o_image = None
p_uuid = None
q_location = None
s_string = None
t_host = None
v_local_variable = None
u_class = None


def init_with_params(input_path=None, sdk_region=None, new_project_name=None, startid=None, sdk_options=None):
    """
    初始化函数，支持参数传入

    Args:
        input_path: 工程路径
        sdk_region: SDK地区 ('1'=国内, '2'=海外)
        new_project_name: 新工程名
        startid: 初始化ID (32位)
        sdk_options: SDK选项
    """
    # 初始化配置文件
    oc_util.init()
    oc_yaml.init()

    ########### 拷贝工程 ###########
    if input_path is None:
        input_path = ''

    # 如果输入为空默认为：/Users/apple/jumbo/xianxian/XXGPlayKit
    if input_path == '':
        input_path = '/Users/apple/jumbo/xianxian/XXGPlayKit'

    # 生成混淆目录
    current_date = time.strftime("%Y%m%d%H%M%S", time.localtime())
    # 获取当前混淆目录
    mix_path = oc_tool.get_current_mix_path(current_date, input_path)
    print('Objective-C本次混淆目录: ', current_date)
    oc_util.path_mix = mix_path
    oc_util.path_mix_project = mix_path + '/混淆后工程'
    # 获取当前工程名
    oc_util.name_current_project = oc_tool.get_current_project_name()
    print('当前工程名: ', oc_util.name_current_project)
    ########### 拷贝工程 ###########

    ########### 获取参数 ###########
    # 非交互模式，使用传入的参数
    custom_util.sdk_cn_or_os = sdk_region or '2'  # 默认海外

    if new_project_name:
        oc_util.new_project_name = new_project_name
    else:
        # 如果没有提供新工程名，生成一个随机名称
        import random
        name = ''
        for _ in range(random.randint(1, 1)):
            name = name + random.choice(oc_util.list_random_words).capitalize()
            name = name + random.choice(oc_util.list_random_words).capitalize()
        oc_util.new_project_name = name

    if startid:
        custom_util.startid = startid
    else:
        custom_util.startid = ''

    if sdk_options:
        custom_util.sdk_options = sdk_options
    else:
        # 设置默认SDK选项
        if custom_util.sdk_cn_or_os == '1':  # 国内
            custom_util.sdk_options = 'ShanYanSDK,BDASignalManager'
        else:  # 海外
            custom_util.sdk_options = 'AppsFlyer,Facebook,Firebase'

    print(f"SDK地区: {'国内' if custom_util.sdk_cn_or_os == '1' else '海外'}")
    print(f"新工程名: {oc_util.new_project_name}")
    print(f"初始化ID: {custom_util.startid or '未设置'}")
    print(f"SDK选项: {custom_util.sdk_options}")
    ########### 获取参数 ###########

    ########### 初始化工具类 ##########
    oc_tool.init()
    ########### 初始化工具类 ##########

    ########### 准备工作 ###########
    custom_start.init()
    ########### 准备工作 ###########


def run_obfuscation(functions=None):
    """
    执行混淆操作

    Args:
        functions: 要执行的功能列表，如 ['1','2','3'] 或 '0' 表示全部
    """
    # 导入功能模块
    if not import_function_modules():
        print("错误: 无法导入必要的功能模块")
        return False

    mix_path = oc_util.path_mix

    # 读取系统framework关键词
    save_system_framework_path = oc_util.get_config_file_path(
        'system_framework_keywords_ios18.2.txt')
    oc_util.list_system_framework_word = oc_util.get_text_lines(
        save_system_framework_path)

    # 读取工程中的framework关键词 封装起来的方法
    save_project_framework_path = mix_path + '/project_framework_keywords.txt'
    custom_a_framework.init_project(save_project_framework_path, 2)
    oc_util.list_project_framework_word = oc_util.get_text_lines(
        save_project_framework_path)

    # xib中关键词加入到系统framework关键词
    save_xib_framework_path = oc_util.get_config_file_path(
        'xib_framework_keywords.txt')
    # 将xib中的关键词加入到系统framework关键词中
    oc_util.list_system_framework_word.extend(
        oc_util.get_text_lines(save_xib_framework_path))

    # 获取工程中字符串的关键词
    save_project_string_path = mix_path + '/project_all_string_words.txt'
    d_string.get_project_string(save_project_string_path)
    oc_util.list_string_words = oc_util.get_text_lines(
        save_project_string_path)

    # 查找工程信息
    custom_h_search_file_content_message.init()

    # 获取要执行的功能列表
    if functions is None:
        # 默认执行全部操作
        func = ['0']
    else:
        func = functions if isinstance(functions, list) else list(functions)

    # 处理功能列表
    if '0' in func:
        func = ['1', '2', '3', '4', '5', '6', '7', '8',
                '9', 'a', 'u', 'b', 'c', 'd', 'e', 'j']
    if 't' in func:
        func = ['1', '3', '4', '5', '6', '7', '8',
                '9', 'a', 'u', 'b', 'c', 'd', 'e']

    # 执行各项功能
    if '1' in func:
        print('1删除注释开始...')
        e_print_annotation.delete_print_or_annotation(1)
        print('1删除注释完成')
    if '2' in func:
        print('2删除打印开始...')
        e_print_annotation.delete_print_or_annotation(2)
        print('2删除打印完成')
    if 'd' in func:
        print('d图片处理开始...')
        o_image.init()
        print('d图片处理完成')
    if '3' in func:
        print('3修改工程名开始...')
        project.modify_project_name(oc_util.new_project_name)
        print('3修改工程名完成')
    if '4' in func:
        print('4修改文件夹名开始...')
        c_folder.modify_project_folder_name()
        print('4修改文件夹名完成')
    if '5' in func:
        print('5修改文件名开始...')
        f_file.modify_oc_file_name()
        print('5修改文件名完成')
    if '6' in func:
        print('6修改通知名开始...')
        g_notification.modify_project_notification()
        print('6修改通知名完成')
    if '9' in func:
        print('9修改block名开始...')
        k_block.init()
        print('9修改block名完成')
    if '7' in func:
        print('7修改属性名和全局变量名开始...')
        i_property.init()
        v_local_variable.init()
        print('7修改属性名和全局变量名完成')
    if '8' in func:
        print('8修改枚举开始...')
        j_enum.init()
        print('8修改枚举完成')
    if 'a' in func:
        print('a修改常量名开始...')
        l_constant.init()
        print('a修改常量名完成')
    if 'b' in func:
        print('b修改delegate名开始...')
        m_delegate.init()
        print('b修改delegate名完成')
    if 'u' in func:
        print('u修改类名开始...')
        u_class.init()
        print('u修改类名完成')
    if 'c' in func:
        print('c修改方法名开始...')
        n_method.init()
        n_c_method.init()
        print('c修改方法名完成')
    if 'e' in func:
        print('e修改uuid开始...')
        p_uuid.init()
        print('e修改uuid完成')
    if 'j' in func:
        print('2删除打印开始...')
        e_print_annotation.delete_print_or_annotation(2)
        print('2删除打印完成')
        # 后续完善
        custom_end.init(custom_util.sdk_cn_or_os)


def run_pbxproj_add_sdk(pbxproj_path, sdk_folder_path, group_name="SDK"):
    """
    执行SDK添加操作

    Args:
        pbxproj_path: project.pbxproj文件路径
        sdk_folder_path: SDK文件夹路径
        group_name: 在项目中创建的组名

    Returns:
        bool: 操作是否成功
    """
    try:
        print(f"📁 开始添加SDK文件夹到项目...")
        print(f"项目文件: {pbxproj_path}")
        print(f"SDK文件夹: {sdk_folder_path}")
        print(f"组名: {group_name}")

        adder = SmartSDKAdder(pbxproj_path)
        success = adder.add_sdk_folder(sdk_folder_path, group_name)

        if success:
            print("✅ SDK文件夹添加成功！")
            print("🎉 现在可以在Xcode中看到添加的SDK文件了！")
            print("📝 Framework作为整体添加，不会单独处理内部文件")
            return True
        else:
            print("❌ SDK文件夹添加失败！")
            return False

    except Exception as e:
        print(f"❌ 添加SDK时发生错误: {e}")
        import traceback
        traceback.print_exc()
        return False


def run_pbxproj_clean(pbxproj_path):
    """
    执行项目清理操作

    Args:
        pbxproj_path: project.pbxproj文件路径

    Returns:
        bool: 操作是否成功
    """
    try:
        print(f"🧹 开始清理第三方文件...")
        print(f"项目文件: {pbxproj_path}")

        cleaner = DemoProjectCleanerSafe(pbxproj_path)
        success = cleaner.clean_all_third_party_files()

        if success:
            print("✅ 项目清理成功！")
            print("🎉 所有第三方文件已从项目中移除！")
            return True
        else:
            print("❌ 项目清理失败！")
            return False

    except Exception as e:
        print(f"❌ 清理项目时发生错误: {e}")
        import traceback
        traceback.print_exc()
        return False


def create_parser():
    """创建命令行参数解析器"""
    parser = argparse.ArgumentParser(
        description='闲闲SDK混淆工具 - 命令行接口',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog='''
使用示例:
  # 代码混淆操作
  python oc_cli.py obfuscate --sdk-region 2
  python oc_cli.py obfuscate --sdk-region 1 --functions 1,2,3
  
  # 添加SDK到项目
  python oc_cli.py add-sdk project.pbxproj SDK_Folder
  python oc_cli.py add-sdk project.pbxproj SDK_Folder --group-name MySDK
  
  # 清理项目中的第三方文件
  python oc_cli.py clean project.pbxproj
  
  # 带完整参数的混淆操作
  python oc_cli.py obfuscate \\
    --input-path /Users/apple/jumbo/xianxian/XXGPlayKit \\
    --sdk-region 2 \\
    --new-project-name MyNewProject \\
    --startid 12345678901234567890123456789012 \\
    --sdk-options "AppsFlyer,Facebook,Firebase" \\
    --functions 0
        '''
    )

    # 创建子命令
    subparsers = parser.add_subparsers(dest='command', help='可用的操作')

    # 混淆子命令
    obfuscate_parser = subparsers.add_parser(
        'obfuscate',
        help='执行代码混淆操作',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog='''
SDK地区选项:
  1 - 国内版本 (默认SDK: ShanYanSDK,BDASignalManager)
  2 - 海外版本 (默认SDK: AppsFlyer,Facebook,Firebase)

功能选项:
  0 - 执行全部操作
  t - 执行半全部操作
  1 - 删除注释
  2 - 删除打印
  3 - 修改工程名
  4 - 修改文件夹名
  5 - 修改文件名
  6 - 修改通知名
  7 - 修改属性名和全局变量名和局部变量名
  8 - 修改枚举
  9 - 修改block名
  a - 修改常量名
  b - 修改delegate名
  c - 修改方法名
  d - 图片处理
  e - 修改uuid
  u - 修改类名
  j - 资源加密等
        '''
    )

    obfuscate_parser.add_argument(
        '--input-path', '-i',
        type=str,
        help='Objective-C工程路径 (默认: /Users/apple/jumbo/xianxian/XXGPlayKit)'
    )

    obfuscate_parser.add_argument(
        '--sdk-region', '-r',
        choices=['1', '2'],
        default='2',
        help='SDK地区: 1=国内, 2=海外 (默认: 2)'
    )

    obfuscate_parser.add_argument(
        '--new-project-name', '-n',
        type=str,
        help='新工程名 (可选，不提供则自动生成)'
    )

    obfuscate_parser.add_argument(
        '--startid', '-s',
        type=str,
        help='初始化ID (必须是32位字符串, 可选)'
    )

    obfuscate_parser.add_argument(
        '--sdk-options', '-o',
        type=str,
        help='SDK选项 (逗号分隔, 如: "AppsFlyer,Facebook,Firebase")'
    )

    obfuscate_parser.add_argument(
        '--functions', '-f',
        type=str,
        default='0',
        help='要执行的功能 (逗号分隔, 如: "1,2,3" 或 "0"表示全部, 默认: 0)'
    )

    # 添加SDK子命令
    add_sdk_parser = subparsers.add_parser(
        'add-sdk',
        help='添加SDK文件夹到Xcode项目',
        description='智能添加SDK文件夹到Xcode项目，支持framework、bundle、library等文件类型'
    )

    add_sdk_parser.add_argument(
        'pbxproj_path',
        help='project.pbxproj文件路径'
    )

    add_sdk_parser.add_argument(
        'sdk_folder_path',
        help='SDK文件夹路径'
    )

    add_sdk_parser.add_argument(
        '--group-name', '-g',
        default='SDK',
        help='在项目中创建的组名 (默认: SDK)'
    )

    # 清理项目子命令
    clean_parser = subparsers.add_parser(
        'clean',
        help='清理项目中的第三方文件',
        description='安全地移除项目中所有第三方framework、library、bundle文件及相关引用'
    )

    clean_parser.add_argument(
        'pbxproj_path',
        help='project.pbxproj文件路径'
    )

    return parser


def validate_args(args):
    """验证命令行参数"""
    errors = []

    if args.command == 'obfuscate':
        # 验证混淆命令的参数
        if hasattr(args, 'startid') and args.startid and len(args.startid) != 32:
            errors.append(f"startid必须是32位字符串，当前长度: {len(args.startid)}")

        # 验证功能选项
        valid_functions = ['0', 't', '1', '2', '3', '4', '5',
                           '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'u', 'j']
        if hasattr(args, 'functions') and args.functions:
            functions = [f.strip() for f in args.functions.split(',')]
            for func in functions:
                if func not in valid_functions:
                    errors.append(f"无效的功能选项: {func}")

    elif args.command == 'add-sdk':
        # 验证SDK添加命令的参数
        if not os.path.exists(args.pbxproj_path):
            errors.append(f"项目文件不存在: {args.pbxproj_path}")

        if not os.path.exists(args.sdk_folder_path):
            errors.append(f"SDK文件夹不存在: {args.sdk_folder_path}")

        if not os.path.isdir(args.sdk_folder_path):
            errors.append(f"SDK路径必须是文件夹: {args.sdk_folder_path}")

    elif args.command == 'clean':
        # 验证清理命令的参数
        if not os.path.exists(args.pbxproj_path):
            errors.append(f"项目文件不存在: {args.pbxproj_path}")

    if errors:
        print("参数验证失败:")
        for error in errors:
            print(f"  - {error}")
        return False

    return True


def main_with_args(args, log_callback=None):
    """使用传入的参数运行混淆（用于GUI调用）"""

    def log(message, level="info"):
        """统一的日志函数"""
        if log_callback:
            log_callback(message, level)
        else:
            print(message)

    # 确保args有command属性，用于GUI调用
    if not hasattr(args, 'command'):
        args.command = 'obfuscate'

    # 验证参数
    log("开始验证参数...")
    if not validate_args(args):
        log("参数验证失败", "error")
        return False
    log("参数验证成功")

    log("=== 闲闲SDK混淆工具 (GUI模式) ===")

    try:
        # 初始化
        log("开始初始化...")
        try:
            init_with_params(
                input_path=args.input_path,
                sdk_region=args.sdk_region,
                new_project_name=args.new_project_name,
                startid=args.startid,
                sdk_options=args.sdk_options
            )
            log("初始化完成")
        except Exception as e:
            log(f"初始化失败: {e}", "error")
            log(f"初始化错误类型: {type(e).__name__}", "error")
            import traceback
            log("初始化错误堆栈:", "error")
            log(traceback.format_exc(), "error")
            return False

        # 执行混淆
        log("开始执行混淆...")
        functions = [f.strip() for f in args.functions.split(',')]
        log(f"将执行功能: {functions}")
        try:
            run_obfuscation(functions=functions)
            log("混淆执行完成")
        except Exception as e:
            log(f"混淆执行失败: {e}", "error")
            log(f"混淆错误类型: {type(e).__name__}", "error")
            import traceback
            log("混淆错误堆栈:", "error")
            log(traceback.format_exc(), "error")
            return False

        log("=== 混淆完成 ===")
        return True

    except KeyboardInterrupt:
        log("操作被用户中断", "warning")
        return False
    except Exception as e:
        log(f"混淆过程中发生错误: {e}", "error")
        log(f"错误类型: {type(e).__name__}", "error")
        import traceback
        log("详细错误堆栈:", "error")
        log(traceback.format_exc(), "error")
        return False


def main():
    """主函数，命令行入口"""
    parser = create_parser()
    args = parser.parse_args()

    # 检查是否提供了命令
    if not args.command:
        parser.print_help()
        print("\n错误: 请指定一个操作命令")
        sys.exit(1)

    success = False

    try:
        if args.command == 'obfuscate':
            # 执行代码混淆
            success = main_with_args(args)

        elif args.command == 'add-sdk':
            # 执行SDK添加
            success = run_pbxproj_add_sdk(
                args.pbxproj_path,
                args.sdk_folder_path,
                args.group_name
            )

        elif args.command == 'clean':
            # 执行项目清理
            success = run_pbxproj_clean(args.pbxproj_path)

        else:
            print(f"错误: 未知的命令 '{args.command}'")
            parser.print_help()
            sys.exit(1)

    except KeyboardInterrupt:
        print("\n操作被用户中断")
        sys.exit(1)
    except Exception as e:
        print(f"执行过程中发生错误: {e}")
        import traceback
        traceback.print_exc()
        sys.exit(1)

    if not success:
        sys.exit(1)


if __name__ == '__main__':
    main()
