#!/usr/bin/env python3
# coding:utf8
"""
测试超时和快速切换机制
演示：
1. HTTP请求10秒超时
2. 超时后立即切换其他数据源（无需等待3次失败）
3. 失败的数据源被标记为不可用
"""

import sys
import os
import time
import logging

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

import pqquotation

# 配置日志以便查看详细信息
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)


def test_timeout_and_switching():
    """测试超时和快速切换机制"""
    print("=" * 70)
    print("测试超时和快速切换机制")
    print("=" * 70)

    # 创建roundrobin实例
    rr = pqquotation.use('roundrobin')

    # 显示初始配置
    print(f"\n【配置信息】")
    print(f"  默认超时时间: {rr._sources['sina'].timeout} 秒")
    print(f"  故障阈值: {rr._failure_threshold} 次连续失败")
    print(f"  重试间隔: {rr._retry_interval} 秒")

    # 显示初始数据源状态
    print(f"\n【初始数据源状态】")
    stats = rr.get_source_stats()
    print(f"  可用数据源: {stats['available_sources']}")
    print(f"  失败数据源: {stats['failed_sources']}")

    # 测试1: 正常请求（观察响应时间）
    print(f"\n【测试1：正常请求】")
    stock_code = '000001'

    start_time = time.time()
    data = rr.real(stock_code)
    elapsed = time.time() - start_time

    if data:
        actual_code = list(data.keys())[0]
        stock_info = data[actual_code]
        print(f"  ✓ 成功获取数据")
        print(f"  股票: {stock_info.get('name', 'N/A')}")
        print(f"  价格: {stock_info.get('now', 'N/A')}")
        print(f"  耗时: {elapsed:.2f} 秒")
    else:
        print(f"  ✗ 获取失败")
        print(f"  耗时: {elapsed:.2f} 秒")

    # 显示数据源统计
    print(f"\n【请求后数据源统计】")
    stats = rr.get_source_stats()
    for source_name, source_stats in stats['sources'].items():
        success_count = source_stats['success']
        failure_count = source_stats['failure']
        avg_time = source_stats['avg_response_time']
        status = "✓ 正常" if source_name not in stats['failed_sources'] else "✗ 失败"
        print(f"  {source_name:10s} {status:8s} | 成功:{success_count}次, 失败:{failure_count}次, 平均:{avg_time:.3f}秒")

    # 显示失败计数
    print(f"\n【失败计数】")
    for source_name, count in stats['failure_counts'].items():
        print(f"  {source_name}: {count}/{stats['failure_threshold']} 次")

    # 测试2: 连续多次请求观察数据源切换
    print(f"\n【测试2：连续请求观察数据源轮换】")
    for i in range(3):
        start_time = time.time()
        data = rr.real(stock_code)
        elapsed = time.time() - start_time

        if data:
            actual_code = list(data.keys())[0]
            stock_name = data[actual_code].get('name', 'N/A')
            print(f"  第{i+1}次: ✓ 成功 | {stock_name} | 耗时 {elapsed:.2f}秒")
        else:
            print(f"  第{i+1}次: ✗ 失败 | 耗时 {elapsed:.2f}秒")

        time.sleep(0.3)  # 短暂间隔

    # 最终统计
    print(f"\n【最终数据源状态】")
    final_stats = rr.get_source_stats()
    print(f"  可用数据源: {final_stats['available_sources']}")
    print(f"  失败数据源: {final_stats['failed_sources']}")

    print(f"\n【健康摘要】")
    print(f"  {rr.get_health_summary()}")

    # 测试3: 超时配置的灵活性
    print(f"\n【测试3：动态调整超时时间】")
    original_timeout = rr._sources['dc'].timeout
    print(f"  原始超时: {original_timeout} 秒")

    # 修改超时为5秒
    for source in rr._sources.values():
        source.timeout = 5
    print(f"  调整为: 5 秒")
    print(f"  说明: 可根据实际情况动态调整超时时间")

    # 恢复原始超时
    for source in rr._sources.values():
        source.timeout = original_timeout

    print(f"\n" + "=" * 70)
    print("测试完成！")
    print("=" * 70)

    print(f"\n【改进总结】")
    print(f"  ✓ P0: 底层HTTP请求已设置10秒超时")
    print(f"  ✓ P1: 超时错误立即切换，无需等待3次失败")
    print(f"  ✓ 失败的数据源被标记为不可用，{rr._retry_interval}秒后自动重试")
    print(f"  ✓ 正常请求响应快速，用户体验显著提升")


def test_timeout_configuration():
    """测试超时配置"""
    print(f"\n" + "=" * 70)
    print("超时配置验证")
    print("=" * 70)

    rr = pqquotation.use('roundrobin')

    print(f"\n【各数据源超时配置】")
    for name, source in rr._sources.items():
        timeout_value = getattr(source, 'timeout', '未设置')
        print(f"  {name:10s}: {timeout_value} 秒")


if __name__ == "__main__":
    try:
        test_timeout_and_switching()
        test_timeout_configuration()
    except KeyboardInterrupt:
        print("\n用户中断测试")
    except Exception as e:
        print(f"\n测试出错: {e}")
        import traceback
        traceback.print_exc()
