#!/usr/bin/env python3
"""
CI/CD 测试脚本
用于持续集成环境中的测试执行
"""

import os
import sys
import json
import time
from pathlib import Path
from datetime import datetime

# 添加项目路径
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

from config.settings import get_settings
from utils.logger import get_logger


class CITestRunner:
    """CI测试运行器"""
    
    def __init__(self):
        self.logger = get_logger()
        self.settings = get_settings()
        self.results = {
            "timestamp": datetime.now().isoformat(),
            "environment": os.environ.get("ENVIRONMENT", "development"),
            "browser": os.environ.get("PLAYWRIGHT_BROWSER", "chromium"),
            "tests": [],
            "summary": {
                "total": 0,
                "passed": 0,
                "failed": 0,
                "skipped": 0,
                "error": 0,
                "duration": 0
            }
        }
    
    def run_smoke_tests(self) -> bool:
        """运行冒烟测试"""
        self.logger.section("运行冒烟测试")
        
        from playwright.sync_api import sync_playwright
        import pytest
        
        pytest_args = [
            "-c", str(project_root / "pytest.ini"),
            "-m", "smoke",
            "-v",
            "--tb=short",
            "--json-report",
            "--json-report-file=reports/smoke_test_results.json",
            "tests"
        ]
        
        try:
            exit_code = pytest.main(pytest_args)
            return exit_code == 0
        except Exception as e:
            self.logger.error(f"冒烟测试失败: {e}")
            return False
    
    def run_regression_tests(self) -> bool:
        """运行回归测试"""
        self.logger.section("运行回归测试")
        
        import pytest
        
        pytest_args = [
            "-c", str(project_root / "pytest.ini"),
            "-m", "regression",
            "-v",
            "--tb=short",
            "--json-report",
            "--json-report-file=reports/regression_test_results.json",
            "tests"
        ]
        
        try:
            exit_code = pytest.main(pytest_args)
            return exit_code == 0
        except Exception as e:
            self.logger.error(f"回归测试失败: {e}")
            return False
    
    def run_performance_tests(self) -> bool:
        """运行性能测试"""
        self.logger.section("运行性能测试")
        
        import pytest
        
        pytest_args = [
            "-c", str(project_root / "pytest.ini"),
            "-m", "performance",
            "-v",
            "--tb=short",
            "--json-report",
            "--json-report-file=reports/performance_test_results.json",
            "tests"
        ]
        
        try:
            exit_code = pytest.main(pytest_args)
            return exit_code == 0
        except Exception as e:
            self.logger.error(f"性能测试失败: {e}")
            return False
    
    def run_cross_browser_tests(self) -> dict:
        """运行跨浏览器测试"""
        self.logger.section("运行跨浏览器测试")
        
        import pytest
        browsers = ["chromium", "firefox", "webkit"]
        results = {}
        
        for browser in browsers:
            self.logger.info(f"测试浏览器: {browser}")
            
            os.environ["PLAYWRIGHT_BROWSER"] = browser
            
            pytest_args = [
                "-c", str(project_root / "pytest.ini"),
                "-m", "smoke",
                "-v",
                "--tb=short",
                f"--json-report=reports/{browser}_test_results.json",
                "tests"
            ]
            
            try:
                exit_code = pytest.main(pytest_args)
                results[browser] = exit_code == 0
            except Exception as e:
                self.logger.error(f"{browser} 测试失败: {e}")
                results[browser] = False
        
        return results
    
    def run_full_test_suite(self) -> bool:
        """运行完整测试套件"""
        self.logger.section("运行完整测试套件")
        
        import pytest
        
        pytest_args = [
            "-c", str(project_root / "pytest.ini"),
            "-v",
            "--tb=short",
            "--json-report",
            "--json-report-file=reports/full_test_results.json",
            "--html=reports/full_test_report.html",
            "--self-contained-html",
            "tests"
        ]
        
        try:
            exit_code = pytest.main(pytest_args)
            return exit_code == 0
        except Exception as e:
            self.logger.error(f"完整测试失败: {e}")
            return False
    
    def generate_ci_report(self, test_results: dict):
        """生成CI测试报告"""
        report_path = Path("reports/ci_test_report.json")
        report_path.parent.mkdir(parents=True, exist_ok=True)
        
        with open(report_path, "w", encoding="utf-8") as f:
            json.dump(test_results, f, indent=2, ensure_ascii=False)
        
        self.logger.info(f"CI报告已生成: {report_path}")
    
    def run_ci_tests(self, test_type: str = "full"):
        """运行CI测试"""
        start_time = time.time()
        
        self.logger.section("开始 CI 测试")
        self.logger.info(f"环境: {self.results['environment']}")
        self.logger.info(f"浏览器: {self.results['browser']}")
        self.logger.info(f"测试类型: {test_type}")
        
        success = False
        
        if test_type == "smoke":
            success = self.run_smoke_tests()
        elif test_type == "regression":
            success = self.run_regression_tests()
        elif test_type == "performance":
            success = self.run_performance_tests()
        elif test_type == "cross_browser":
            cross_results = self.run_cross_browser_tests()
            success = all(cross_results.values())
            self.results["cross_browser_results"] = cross_results
        elif test_type == "full":
            success = self.run_full_test_suite()
        else:
            self.logger.error(f"未知的测试类型: {test_type}")
            return False
        
        end_time = time.time()
        self.results["summary"]["duration"] = end_time - start_time
        self.results["success"] = success
        
        self.logger.section("CI 测试完成")
        self.logger.info(f"总耗时: {self.results['summary']['duration']:.2f}秒")
        self.logger.info(f"测试结果: {'成功' if success else '失败'}")
        
        # 生成报告
        self.generate_ci_report(self.results)
        
        return success


def parse_ci_arguments():
    """解析CI参数"""
    parser = argparse.ArgumentParser(
        description="Novalon Website CI 测试运行器"
    )
    
    parser.add_argument(
        "--test-type",
        default="full",
        choices=["smoke", "regression", "performance", "cross_browser", "full"],
        help="测试类型 (默认: full)"
    )
    
    parser.add_argument(
        "--env",
        default="development",
        choices=["development", "staging", "production"],
        help="测试环境 (默认: development)"
    )
    
    parser.add_argument(
        "--browser",
        default="chromium",
        choices=["chromium", "firefox", "webkit", "all"],
        help="浏览器 (默认: chromium)"
    )
    
    parser.add_argument(
        "--report-dir",
        default="reports",
        help="报告目录 (默认: reports)"
    )
    
    return parser.parse_args()


def main():
    """CI主函数"""
    args = parse_ci_arguments()
    
    # 设置环境变量
    os.environ["ENVIRONMENT"] = args.env
    os.environ["PLAYWRIGHT_BROWSER"] = args.browser
    os.environ["REPORT_DIR"] = args.report_dir
    
    # 确保报告目录存在
    Path(args.report_dir).mkdir(parents=True, exist_ok=True)
    
    # 运行测试
    runner = CITestRunner()
    success = runner.run_ci_tests(args.test_type)
    
    # 输出结果
    if success:
        print("\n✅ CI 测试通过")
        sys.exit(0)
    else:
        print("\n❌ CI 测试失败")
        sys.exit(1)


if __name__ == "__main__":
    main()
