#!/usr/bin/env python3
"""Main test runner for differential testing framework."""

import sys
import argparse
from datetime import datetime
from pathlib import Path

# Add parent directory to path
sys.path.insert(0, str(Path(__file__).parent))

from test_generator import TestCaseGenerator
from differential_tester import DifferentialTester


def run_smoke_tests():
    """Run quick smoke tests."""
    print("Running smoke tests...")
    gen = TestCaseGenerator(seed=42)
    tester = DifferentialTester()

    # Basic expressions
    basic_exprs = gen.generate_basic_expressions()[:10]
    test_cases = []
    for expr in basic_exprs:
        test_cases.append({
            'expr': expr,
            'start': datetime(2020, 1, 1, 0, 0, 0),
            'iterations': 5,
            'description': f'Basic: {expr}'
        })

    tester.run_test_suite(test_cases, "Smoke Tests")
    tester.save_results('/home/ubuntu-exp/cronproject/croniter-rs/tests/differential/smoke_results.json')
    tester.print_summary()

    return tester.results['failed'] == 0 and tester.results['errors'] == 0


def run_comprehensive_tests():
    """Run comprehensive test suite."""
    print("Running comprehensive tests...")
    gen = TestCaseGenerator(seed=42)
    tester = DifferentialTester()

    # 1. Basic expressions
    basic_exprs = gen.generate_basic_expressions()
    test_cases = []
    for expr in basic_exprs:
        test_cases.append({
            'expr': expr,
            'start': datetime(2020, 1, 1, 0, 0, 0),
            'iterations': 10,
            'description': f'Basic: {expr}'
        })
    tester.run_test_suite(test_cases, "Basic Expressions")

    # 2. Hash expressions
    test_cases = []
    for expr, hash_id in gen.generate_hash_expressions():
        test_cases.append({
            'expr': expr,
            'start': datetime(2020, 1, 1, 0, 0, 0),
            'iterations': 10,
            'hash_id': hash_id,
            'description': f'Hash: {expr} (id={hash_id})'
        })
    tester.run_test_suite(test_cases, "Hash Expressions")

    # 3. Boundary dates
    test_cases = []
    for dt in gen.generate_boundary_dates():
        for expr in ['* * * * *', '0 0 * * *', '0 0 1 * *', '0 0 * * 0']:
            test_cases.append({
                'expr': expr,
                'start': dt,
                'iterations': 5,
                'description': f'Boundary date: {expr} @ {dt}'
            })
    tester.run_test_suite(test_cases, "Boundary Dates")

    # 4. Equivalence classes
    test_cases = gen.generate_equivalence_classes()
    tester.run_test_suite(test_cases, "Equivalence Classes")

    # 5. Boundary values
    test_cases = gen.generate_boundary_value_tests()
    tester.run_test_suite(test_cases, "Boundary Values")

    # Save results
    tester.save_results('/home/ubuntu-exp/cronproject/croniter-rs/tests/differential/comprehensive_results.json')
    tester.print_summary()

    return tester.results['failed'] == 0 and tester.results['errors'] == 0


def run_fuzzing_tests(duration_hours: int = 24, parallel: bool = False):
    """Run fuzzing tests for specified duration."""
    print(f"Running fuzzing tests for {duration_hours} hours...")
    print("WARNING: This will generate and test thousands of random cases")

    gen = TestCaseGenerator(seed=None)  # Random seed for fuzzing
    tester = DifferentialTester(log_file="/tmp/differential_fuzzing.log")

    import time
    start_time = time.time()
    end_time = start_time + (duration_hours * 3600)

    batch_num = 0
    total_tests = 0

    while time.time() < end_time:
        batch_num += 1
        print(f"\nFuzzing batch {batch_num}...")

        # Generate batch of test cases
        test_cases = gen.generate_fuzzing_cases(count=100)
        total_tests += len(test_cases)

        tester.run_test_suite(test_cases, f"Fuzzing Batch {batch_num}")

        # Save intermediate results
        tester.save_results(f'/home/ubuntu-exp/cronproject/croniter-rs/tests/differential/fuzzing_batch_{batch_num}.json')

        elapsed = time.time() - start_time
        remaining = end_time - time.time()
        print(f"Elapsed: {elapsed/3600:.2f}h, Remaining: {remaining/3600:.2f}h, Total tests: {total_tests}")

        if tester.results['failed'] > 100:
            print("WARNING: Too many failures, stopping fuzzing")
            break

    tester.save_results('/home/ubuntu-exp/cronproject/croniter-rs/tests/differential/fuzzing_final.json')
    tester.print_summary()

    return tester.results['failed'] == 0 and tester.results['errors'] == 0


def run_quick_fuzzing(count: int = 100):
    """Run quick fuzzing test with specified count."""
    print(f"Running quick fuzzing with {count} test cases...")
    gen = TestCaseGenerator(seed=42)
    tester = DifferentialTester()

    test_cases = gen.generate_fuzzing_cases(count=count)
    tester.run_test_suite(test_cases, f"Quick Fuzzing ({count} cases)")

    tester.save_results('/home/ubuntu-exp/cronproject/croniter-rs/tests/differential/quick_fuzz_results.json')
    tester.print_summary()

    return tester.results['failed'] == 0 and tester.results['errors'] == 0


def main():
    parser = argparse.ArgumentParser(description='Differential testing framework for croniter-rs')
    parser.add_argument('mode', choices=['smoke', 'comprehensive', 'fuzz', 'quick-fuzz'],
                       help='Test mode to run')
    parser.add_argument('--duration', type=int, default=24,
                       help='Duration in hours for fuzzing (default: 24)')
    parser.add_argument('--count', type=int, default=100,
                       help='Number of test cases for quick-fuzz (default: 100)')
    parser.add_argument('--parallel', action='store_true',
                       help='Run tests in parallel (for fuzzing)')

    args = parser.parse_args()

    print(f"{'='*80}")
    print("Croniter-rs Differential Testing Framework")
    print(f"{'='*80}")
    print(f"Mode: {args.mode}")
    print(f"Time: {datetime.now()}")
    print(f"{'='*80}\n")

    success = False

    if args.mode == 'smoke':
        success = run_smoke_tests()
    elif args.mode == 'comprehensive':
        success = run_comprehensive_tests()
    elif args.mode == 'fuzz':
        success = run_fuzzing_tests(duration_hours=args.duration, parallel=args.parallel)
    elif args.mode == 'quick-fuzz':
        success = run_quick_fuzzing(count=args.count)

    print(f"\n{'='*80}")
    print(f"Test run completed: {'SUCCESS' if success else 'FAILURES DETECTED'}")
    print(f"{'='*80}")

    sys.exit(0 if success else 1)


if __name__ == '__main__':
    main()
