# -*- coding: utf-8 -*-
"""
统一测试执行文件
支持批量运行所有用例、按标签运行、按目录运行等
"""
import argparse
import os
import subprocess
import sys

# 添加项目根目录到 Python 路径
current_file_path = os.path.abspath(__file__)
project_root = os.path.abspath(os.path.join(os.path.dirname(current_file_path), '../../'))
if project_root not in sys.path:
    sys.path.insert(0, project_root)

print(project_root)
# 测试目录
TEST_CASE_DIR = 'zhyy/test_case/TestCase'
case_dir = os.path.join(project_root,TEST_CASE_DIR)
# 报告目录
REPORT_DIR = os.path.join(os.path.dirname(current_file_path), 'reports')
ALLURE_RESULTS_DIR = os.path.join(project_root, 'allure-results')
ALLURE_REPORT_DIR = os.path.join(project_root, 'allure-report')

print(ALLURE_REPORT_DIR)
def ensure_dirs():
    """确保报告目录存在"""
    os.makedirs(ALLURE_RESULTS_DIR, exist_ok=True)
    os.makedirs(ALLURE_REPORT_DIR, exist_ok=True)


def run_pytest(args_list):
    """执行pytest命令"""
    # 设置PYTHONPATH环境变量
    env = os.environ.copy()
    env['PYTHONPATH'] = project_root + (os.pathsep + env['PYTHONPATH'] if 'PYTHONPATH' in env else '')

    # 检测Jenkins环境
    is_jenkins = 'JENKINS_URL' in env or 'BUILD_NUMBER' in env
    if is_jenkins and 'WORKSPACE' in env:
        # Jenkins环境下使用绝对路径
        global ALLURE_RESULTS_DIR, ALLURE_REPORT_DIR
        ALLURE_RESULTS_DIR = os.path.join(env['WORKSPACE'], 'zhyy', 'test_case', 'reports', 'allure-results')
        ALLURE_REPORT_DIR = os.path.join(env['WORKSPACE'], 'zhyy', 'test_case', 'reports', 'allure-report')
        ensure_dirs()

    cmd = ['python', '-m', 'pytest'] + args_list
    print(f"执行命令: {' '.join(cmd)}")

    # 执行命令
    result = subprocess.run(' '.join(cmd), shell=True, cwd=project_root, env=env)
    return result.returncode


def find_test_files(directory):
    """递归查找所有测试文件"""
    test_files = []
    for root, dirs, files in os.walk(directory):
        for file in files:
            if file.endswith('.py') and not file.startswith('__'):
                test_files.append(os.path.join(root, file))
    return test_files


def run_tests(target, test_type='all', **kwargs):
    """运行测试"""
    base_args = ['-v', '--tb=short', f'--alluredir={ALLURE_RESULTS_DIR}']

    if test_type == 'all':
        print("运行所有测试用例...")
        test_files = find_test_files(case_dir)
        if not test_files:
            print("错误: 未找到测试文件")
            return 1
        args = test_files + base_args
    elif test_type == 'feature':
        print(f"按feature标签运行: {target}")
        test_files = find_test_files(case_dir)
        if not test_files:
            print("错误: 未找到测试文件")
            return 1
        args = test_files + [f'--allure-features={target}'] + base_args
    elif test_type == 'story':
        print(f"按story标签运行: {target}")
        test_files = find_test_files(case_dir)
        if not test_files:
            print("错误: 未找到测试文件")
            return 1
        args = test_files + [f'--allure-stories={target}'] + base_args
    elif test_type == 'marker':
        print(f"按pytest标记运行: {target}")
        test_files = find_test_files(case_dir)
        if not test_files:
            print("错误: 未找到测试文件")
            return 1
        args = test_files + [f'-m={target}'] + base_args
    elif test_type == 'dir':
        full_path = os.path.join(case_dir, target)
        if not os.path.exists(full_path):
            print(f"错误: 目录不存在: {full_path}")
            return 1
        print(f"按目录运行: {target}")
        test_files = find_test_files(full_path)
        if not test_files:
            print("错误: 未找到测试文件")
            return 1
        args = test_files + base_args
    elif test_type == 'file':
        full_path = os.path.join(case_dir, target)
        if not os.path.exists(full_path):
            print(f"错误: 文件不存在: {full_path}")
            return 1
        print(f"按文件运行: {target}")
        args = [full_path] + base_args
    elif test_type == 'keyword':
        print(f"按关键字运行: {target}")
        test_files = find_test_files(case_dir)
        if not test_files:
            print("错误: 未找到测试文件")
            return 1
        args = test_files + [f'-k={target}'] + base_args
    else:
        print(f"错误: 未知的测试类型: {test_type}")
        return 1

    return run_pytest(args)


def generate_allure_report():
    """生成allure报告"""
    print("生成Allure报告...")
    cmd = f'allure generate {ALLURE_RESULTS_DIR} -o {ALLURE_REPORT_DIR} --clean'

    try:
        subprocess.run(cmd, shell=True, check=True)
        print(f"Allure报告生成成功: {ALLURE_REPORT_DIR}")
        print(f"打开报告命令: allure open {ALLURE_REPORT_DIR}")
        return 0
    except subprocess.CalledProcessError as e:
        print(f"生成Allure报告失败: {e}")
        return 1
    except FileNotFoundError:
        print("警告: 未找到allure命令，请先安装allure")
        return 1


def open_allure_report():
    """打开allure报告"""
    print("打开Allure报告...")
    cmd = f'allure open {ALLURE_REPORT_DIR}'

    try:
        subprocess.Popen(cmd, shell=True)
        print("Allure报告已在浏览器中打开")
    except FileNotFoundError:
        print("警告: 未找到allure命令，请先安装allure")


def main():
    parser = argparse.ArgumentParser(
        description='统一测试执行工具',
        epilog="""
使用示例:
  # 运行所有测试
  python run_tests.py

  # 按feature标签运行
  python run_tests.py --feature "深圳采购工作台采购订单页面"

  # 按目录运行
  python run_tests.py --dir "接口/SZPurchase"

  # 生成并打开报告
  python run_tests.py --report --open
        """
    )

    # 运行选项
    run_group = parser.add_mutually_exclusive_group(required=False)
    run_group.add_argument('--feature', type=str, help='按allure feature标签运行')
    run_group.add_argument('--story', type=str, help='按allure story标签运行')
    run_group.add_argument('--dir', type=str, help='按目录运行（相对于TestCase目录）')
    run_group.add_argument('--file', type=str, help='按文件运行（相对于TestCase目录）')
    run_group.add_argument('--keyword', type=str, help='按关键字运行')
    run_group.add_argument('--marker', type=str, help='按pytest标记运行')

    # 报告选项
    parser.add_argument('--report', action='store_true', help='生成Allure报告')
    parser.add_argument('--open', action='store_true', help='打开Allure报告')
    parser.add_argument('--no-report', action='store_true', help='不生成Allure报告')

    args = parser.parse_args()

    # 确保目录存在
    ensure_dirs()

    # 执行测试
    exit_code = 0
    if args.feature:
        exit_code = run_tests(args.feature, 'feature')
    elif args.story:
        exit_code = run_tests(args.story, 'story')
    elif args.dir:
        exit_code = run_tests(args.dir, 'dir')
    elif args.file:
        exit_code = run_tests(args.file, 'file')
    elif args.keyword:
        exit_code = run_tests(args.keyword, 'keyword')
    elif args.marker:
        exit_code = run_tests(args.marker, 'marker')
    else:
        # 默认运行所有测试
        exit_code = run_tests(None, 'all')

    # 生成报告
    if args.report or (not args.no_report and exit_code == 0):
        generate_allure_report()
        if args.open:
            open_allure_report()

    print("=" * 80)
    print("✓ 测试执行完成" if exit_code == 0 else f"✗ 测试执行失败，退出码: {exit_code}")
    print("=" * 80)

    sys.exit(exit_code)


if __name__ == '__main__':
    main()
