import sys
import os
from unittest.mock import patch, MagicMock

sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from database.options import ReleaseOptions

def test_basic_required_args():
    """测试基本必需参数"""
    # 构建必需参数
    test_args = [
        '--SWBoardAlias', 'testboard',
        '--TagId', 'v1.0.0',
        '--SnapShotXml', 'snapshot.xml',
        '--SWBoardType', 'boardtype',
        '--SWProductType', 'producttype'
    ]
    
    # 解析参数
    ReleaseOptions.parse(test_args)
    
    # 验证必需参数被正确解析 使用属性的方式访问
    assert ReleaseOptions.SWBoardAlias == 'testboard'
    assert ReleaseOptions.TagId == 'v1.0.0'
    assert ReleaseOptions.SnapShotXml == 'snapshot.xml'
    assert ReleaseOptions.SWBoardType == 'boardtype'
    assert ReleaseOptions.SWProductType == 'producttype'
    
    # 验证非必需参数使用默认值
    assert ReleaseOptions['ThreadNum'] == 1
    assert ReleaseOptions['IplVersion'] == 'CN'
    assert ReleaseOptions['SkipCheckout'] is False
    assert ReleaseOptions['OpenSource'] is False
    
    assert ReleaseOptions.check() is True


def test_bool_args():
    """测试布尔类型的参数"""
    test_args = [
        '--SWBoardAlias', 'testboard',
        '--TagId', 'v1.0.0',
        '--SnapShotXml', 'snapshot.xml',
        '--SWBoardType', 'boardtype',
        '--SWProductType', 'producttype',
        '--SkipCheckout',
        '--OpenSource',
        '--RiscVSupport',
        '--Cm4Support',
        '--Doc2Pdf',
        '--Doc2Html',
        '--VerifyBuild',
        '--ReduceCodeSize',
        '--SkipSyncCode'
    ]
    
    ReleaseOptions.parse(test_args)
    
    # 验证布尔参数被正确解析
    assert ReleaseOptions['SkipCheckout'] is True
    assert ReleaseOptions['OpenSource'] is True
    assert ReleaseOptions['RiscVSupport'] is True
    assert ReleaseOptions['Cm4Support'] is True
    assert ReleaseOptions['Doc2Pdf'] is True
    assert ReleaseOptions['Doc2Html'] is True
    assert ReleaseOptions['VerifyBuild'] is True
    assert ReleaseOptions['ReduceCodeSize'] is True
    assert ReleaseOptions['SkipSyncCode'] is True
    
    assert ReleaseOptions.check() is True


def test_optional_args():
    """测试可选参数"""
    test_args = [
        '--SWBoardAlias', 'testboard',
        '--TagId', 'v1.0.0',
        '--SnapShotXml', 'snapshot.xml',
        '--SWBoardType', 'boardtype',
        '--SWProductType', 'producttype',
        '--DocsPath', '/path/to/docs',
        '--HWChipType', 'chiptype',
        '--HWPackageType', 'package',
        '--OutPath', 'output_dir',
        '--ThreadNum', '8',
        '--IplVersion', 'WW'
    ]
    
    ReleaseOptions.parse(test_args)
    
    # 验证可选参数被正确解析
    assert ReleaseOptions['DocsPath'] == '/path/to/docs'
    assert ReleaseOptions['HWChipType'] == 'chiptype'
    assert ReleaseOptions['HWPackageType'] == 'package'
    assert ReleaseOptions['OutPath'] == 'output_dir'
    assert ReleaseOptions['ThreadNum'] == 8
    assert ReleaseOptions['IplVersion'] == 'WW'
    
    assert ReleaseOptions.check() is True


def test_mix_args():
    """测试混合使用短格式和长格式参数"""
    test_args = [
        '-a', 'testboard',
        '-t', 'v1.0.0',
        '-s', 'snapshot.xml',
        '-b', 'boardtype',
        '-p', 'producttype',
        '-d', '/path/to/docs',
        '-j', '4',
        '-i',  # SkipCheckout
        '-f'   # OpenSource
    ]

    ReleaseOptions.parse(test_args)
    
    # 验证短格式参数被正确解析
    assert ReleaseOptions['SWBoardAlias'] == 'testboard'
    assert ReleaseOptions['TagId'] == 'v1.0.0'
    assert ReleaseOptions['DocsPath'] == '/path/to/docs'
    assert ReleaseOptions['ThreadNum'] == 4
    assert ReleaseOptions['SkipCheckout'] is True
    assert ReleaseOptions['OpenSource'] is True
    
    assert ReleaseOptions.check() is True


def test_missing_required_args():
    """测试缺少必需参数的情况"""
    # 缺少必需参数 SWBoardType
    test_args = [
        '--SWBoardAlias', 'testboard',
        '--TagId', 'v1.0.0',
        '--SnapShotXml', 'snapshot.xml',
        '--SWProductType', 'producttype'
    ]
    
    try:
        ReleaseOptions.parse(test_args)
    except SystemExit as e:
        assert True


def test_invalid_thread_num():
    """测试无效的线程数"""
    test_args = [
        '--SWBoardAlias', 'testboard',
        '--TagId', 'v1.0.0',
        '--SnapShotXml', 'snapshot.xml',
        '--SWBoardType', 'boardtype',
        '--SWProductType', 'producttype',
        '--ThreadNum', '-1'  # 无效的线程数
    ]
    
    ReleaseOptions.parse(test_args)
    
    # 线程数被解析但无效
    assert ReleaseOptions['ThreadNum'] == -1
    
    # 检查应该失败
    try:
        ReleaseOptions.check()
    except ValueError as e:
        assert str(e) == "ThreadNum 必须为正整数"


def test_ipl_version_choices():
    """测试 IplVersion 的选择限制"""
    # 备份原始的 ReleaseOptions 实例
    original_instance = ReleaseOptions._instance
    
    try:
        # 有效的 IplVersion: 'CN'
        test_args = [
            '--SWBoardAlias', 'testboard',
            '--TagId', 'v1.0.0',
            '--SnapShotXml', 'snapshot.xml',
            '--SWBoardType', 'boardtype',
            '--SWProductType', 'producttype',
            '--IplVersion', 'CN'
        ]
        
        ReleaseOptions.parse(test_args)
        assert ReleaseOptions['IplVersion'] == 'CN'
        assert ReleaseOptions.check() is True
        
        # 有效的 IplVersion: 'WW'
        test_args[-1] = 'WW'
        ReleaseOptions.parse(test_args)
        assert ReleaseOptions['IplVersion'] == 'WW'
        assert ReleaseOptions.check() is True
        
        # 无效的 IplVersion
        test_args[-1] = 'INVALID'
        try:
            ReleaseOptions.parse(test_args)
        except SystemExit as e:
            assert True
    finally:
        # 恢复原始的 ReleaseOptions 实例
        ReleaseOptions._instance = original_instance

@patch('database.options.get_alkaid_root')  # 修改patch路径为正确的模块路径
def test_default_alkaid_root_path(mock_get_alkaid_root):
    """测试默认的 AlkaidRootPath"""
    # 设置 mock 返回值
    mock_get_alkaid_root.return_value = '/mocked/alkaid/root'
    
    test_args = [
        '--SWBoardAlias', 'testboard',
        '--TagId', 'v1.0.0',
        '--SnapShotXml', 'snapshot.xml',
        '--SWBoardType', 'boardtype',
        '--SWProductType', 'producttype'
    ]
    
    # 重置 ReleaseOptions 实例，确保使用新的 mock
    ReleaseOptions._instance = None
    
    # 重新初始化 ReleaseOptions 实例
    ReleaseOptions.__class__().parse(test_args)
    
    # 验证 AlkaidRootPath 使用 get_alkaid_root 的返回值
    assert ReleaseOptions['AlkaidRootPath'] == '/mocked/alkaid/root'
    mock_get_alkaid_root.assert_called_once()


def test_dict_interface():
    """测试字典接口功能"""
    test_args = [
        '--SWBoardAlias', 'testboard',
        '--TagId', 'v1.0.0',
        '--SnapShotXml', 'snapshot.xml',
        '--SWBoardType', 'boardtype',
        '--SWProductType', 'producttype'
    ]
    
    ReleaseOptions.parse(test_args)
    
    # 测试 __getitem__
    assert ReleaseOptions['SWBoardAlias'] == 'testboard'
    
    # 测试 __setitem__
    ReleaseOptions['OutPath'] = 'custom_output'
    assert ReleaseOptions['OutPath'] == 'custom_output'
    
    # 测试 __contains__
    assert 'SWBoardAlias' in ReleaseOptions
    assert 'OutPath' in ReleaseOptions
    assert 'NonExistentKey' not in ReleaseOptions


def test_mounriver_sdk_with_riscv():
    """测试 MounRiverSDK 和 RiscVSupport 的组合"""
    test_args = [
        '--SWBoardAlias', 'testboard',
        '--TagId', 'v1.0.0',
        '--SnapShotXml', 'snapshot.xml',
        '--SWBoardType', 'boardtype',
        '--SWProductType', 'producttype',
        '--RiscVSupport',
        '--MounRiverSDK'
    ]
    
    ReleaseOptions.parse(test_args)
    
    # 验证两个参数都被正确设置
    assert ReleaseOptions['RiscVSupport'] is True
    assert ReleaseOptions['MounRiverSDK'] is True
    
    assert ReleaseOptions.check() is True


def test_help_method():
    """测试 help 方法"""
    # 备份原始解析器
    original_parser = getattr(ReleaseOptions, 'parser', None)
    
    try:
        # 准备一个 MagicMock 来捕获 print_help 的调用
        ReleaseOptions.parser = MagicMock()
        
        # 调用 help 方法
        ReleaseOptions.help()
        
        # 验证 print_help 被调用
        ReleaseOptions.parser.print_help.assert_called_once()
    finally:
        # 恢复原始解析器
        ReleaseOptions.parser = original_parser
