#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
OPC UA模块快速测试
简单验证OPC UA内置函数模块的基本功能
"""

import sys
import os
import time

# 添加项目根目录到路径
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))

from services.online_script.built_in_modules.opc_ua_module import VWEDOpcUaModule
from tests.test_opc_ua_server import OpcUaTestServer


def test_basic_functionality():
    """测试基本功能"""
    print("=" * 60)
    print("OPC UA模块基本功能测试")
    print("=" * 60)
    
    # 1. 启动测试服务器
    print("\n1. 启动OPC UA测试服务器...")
    server = OpcUaTestServer(host='localhost', port=4840)
    
    try:
        server.start_server()
        time.sleep(2)  # 等待服务器启动
        
        server_info = server.get_server_info()
        endpoint = server_info['endpoint']
        namespace_idx = server_info['namespace_index']
        
        print(f"   服务器端点: {endpoint}")
        print(f"   命名空间索引: {namespace_idx}")
        print("   服务器启动成功！")
        
        # 2. 创建OPC UA模块实例
        print("\n2. 创建OPC UA模块实例...")
        opc_module = VWEDOpcUaModule("test_script")
        print("   模块实例创建成功！")
        
        # 3. 测试读取功能
        print("\n3. 测试读取功能...")
        
        # 测试读取整数节点
        try:
            value = opc_module.read_opc_value_with_namespace(namespace_idx, "i=1001", endpoint)
            print(f"   ✓ 读取整数节点: ns={namespace_idx};i=1001 = {value}")
        except Exception as e:
            print(f"   ✗ 读取整数节点失败: {e}")
        
        # 测试读取字符串节点
        try:
            value = opc_module.read_opc_value_with_namespace(namespace_idx, "s=StringNodeId", endpoint)
            print(f"   ✓ 读取字符串节点: ns={namespace_idx};s=StringNodeId = {value}")
        except Exception as e:
            print(f"   ✗ 读取字符串节点失败: {e}")
        
        # 测试读取动态节点
        try:
            value = opc_module.read_opc_value_with_namespace(namespace_idx, "Counter", endpoint)
            print(f"   ✓ 读取计数器节点: ns={namespace_idx};Counter = {value}")
        except Exception as e:
            print(f"   ✗ 读取计数器节点失败: {e}")
        
        # 4. 测试写入功能
        print("\n4. 测试写入功能...")
        
        try:
            # 先读取原始值
            original_value = opc_module.read_opc_value_with_namespace(namespace_idx, "i=1001", endpoint)
            print(f"   原始值: {original_value}")
            
            # 写入新值
            new_value = 12345
            result = opc_module.write_opc_value_with_namespace(namespace_idx, "i=1001", new_value, endpoint)
            print(f"   ✓ 写入新值 {new_value}: {result}")
            
            # 验证写入
            written_value = opc_module.read_opc_value_with_namespace(namespace_idx, "i=1001", endpoint)
            print(f"   ✓ 验证写入值: {written_value}")
            
            if written_value == new_value:
                print("   ✓ 写入验证成功！")
            else:
                print("   ✗ 写入验证失败！")
            
            # 恢复原始值
            opc_module.write_opc_value_with_namespace(namespace_idx, "i=1001", original_value, endpoint)
            print(f"   ✓ 恢复原始值: {original_value}")
            
        except Exception as e:
            print(f"   ✗ 写入测试失败: {e}")
        
        # 5. 测试订阅功能
        print("\n5. 测试订阅功能...")
        
        try:
            # 创建订阅
            value1 = opc_module.read_opc_value_by_subscription(namespace_idx, "Counter", endpoint)
            print(f"   ✓ 订阅计数器（第一次）: {value1}")
            
            # 等待值变化
            print("   等待3秒让值发生变化...")
            time.sleep(3)
            
            # 再次读取订阅值
            value2 = opc_module.read_opc_value_by_subscription(namespace_idx, "Counter", endpoint)
            print(f"   ✓ 订阅计数器（第二次）: {value2}")
            
            if value1 != value2:
                print("   ✓ 订阅功能正常，值发生了变化！")
            else:
                print("   ! 订阅功能可能有问题，值没有变化")
                
        except Exception as e:
            print(f"   ✗ 订阅测试失败: {e}")
        
        # 6. 测试错误处理
        print("\n6. 测试错误处理...")
        
        # 测试读取不存在的节点
        try:
            opc_module.read_opc_value_with_namespace(namespace_idx, "i=99999", endpoint)
            print("   ✗ 应该抛出异常但没有抛出")
        except RuntimeError as e:
            if str(e) == "read_opc_value error":
                print("   ✓ 正确处理不存在节点的错误")
            else:
                print(f"   ! 异常消息不正确: {e}")
        except Exception as e:
            print(f"   ! 异常类型不正确: {e}")
        
        # 7. 显示动态数据
        print("\n7. 监控动态数据（5秒）...")
        start_time = time.time()
        while time.time() - start_time < 5:
            try:
                counter = opc_module.read_opc_value_with_namespace(namespace_idx, "Counter", endpoint)
                temp = opc_module.read_opc_value_with_namespace(namespace_idx, "Temperature", endpoint)
                bool_val = opc_module.read_opc_value_with_namespace(namespace_idx, "BooleanVariable", endpoint)
                
                timestamp = time.strftime('%H:%M:%S')
                print(f"   [{timestamp}] 计数器: {counter}, 温度: {temp:.2f}°C, 布尔值: {bool_val}")
                time.sleep(1)
                
            except Exception as e:
                print(f"   监控错误: {e}")
                break
        
        # 8. 清理资源
        print("\n8. 清理资源...")
        opc_module.cleanup()
        print("   ✓ OPC UA模块资源清理完成")
        
        print("\n" + "=" * 60)
        print("✓ 基本功能测试完成！")
        print("=" * 60)
        
    except Exception as e:
        print(f"测试过程中发生错误: {e}")
        import traceback
        traceback.print_exc()
        
    finally:
        # 停止服务器
        print("\n停止测试服务器...")
        server.stop_server()
        print("测试服务器已停止")


def show_server_info():
    """显示服务器信息"""
    print("=" * 60)
    print("OPC UA测试服务器信息")
    print("=" * 60)
    
    server = OpcUaTestServer(host='localhost', port=4840)
    
    try:
        server.start_server()
        time.sleep(2)
        
        server_info = server.get_server_info()
        node_info = server.get_node_info()
        
        print(f"\n服务器信息:")
        print(f"  端点: {server_info['endpoint']}")
        print(f"  主机: {server_info['host']}")
        print(f"  端口: {server_info['port']}")
        print(f"  运行状态: {server_info['running']}")
        print(f"  命名空间索引: {server_info['namespace_index']}")
        
        print(f"\n可用测试节点:")
        if node_info:
            for name, info in node_info.items():
                node_id_full = f"ns={info['namespace_index']};{info['node_id']}"
                print(f"  {name}:")
                print(f"    NodeId: {node_id_full}")
                print(f"    值: {info['value']} ({info['data_type']})")
        
        print(f"\n使用示例:")
        print(f"# Python代码示例")
        print(f"from services.online_script.built_in_modules.opc_ua_module import VWEDOpcUaModule")
        print(f"opc = VWEDOpcUaModule('test')")
        print(f"")
        print(f"# 读取整数节点")
        print(f"value = opc.read_opc_value_with_namespace({server_info['namespace_index']}, 'i=1001', '{server_info['endpoint']}')")
        print(f"print(f'整数节点值: {{value}}')")
        print(f"")
        print(f"# 写入值")
        print(f"result = opc.write_opc_value_with_namespace({server_info['namespace_index']}, 'i=1001', 8888, '{server_info['endpoint']}')")
        print(f"print(f'写入结果: {{result}}')")
        print(f"")
        print(f"# 订阅读取")
        print(f"value = opc.read_opc_value_by_subscription({server_info['namespace_index']}, 'Counter', '{server_info['endpoint']}')")
        print(f"print(f'订阅值: {{value}}')")
        
    except Exception as e:
        print(f"启动服务器失败: {e}")
        
    finally:
        server.stop_server()


def main():
    """主函数"""
    print("VWED OPC UA模块测试工具")
    print("请选择操作:")
    print("1. 运行基本功能测试")
    print("2. 显示服务器信息和使用示例")
    
    choice = input("请输入选择 (1 或 2, 默认1): ").strip()
    
    if choice == "2":
        show_server_info()
    else:
        test_basic_functionality()


if __name__ == "__main__":
    main()