#!/usr/bin/env python3
"""
Test Runner for Skill Jangler
Runs all test suites and generates a comprehensive test report
"""

import sys
import unittest
import os
from io import StringIO
from pathlib import Path


class ColoredTextTestResult(unittest.TextTestResult):
    """Custom test result class with colored output"""

    # ANSI color codes
    GREEN = '\033[92m'
    RED = '\033[91m'
    YELLOW = '\033[93m'
    BLUE = '\033[94m'
    RESET = '\033[0m'
    BOLD = '\033[1m'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.test_results = []

    def addSuccess(self, test):
        super().addSuccess(test)
        self.test_results.append(('PASS', test))
        if self.showAll:
            self.stream.write(f"{self.GREEN}✓ PASS{self.RESET}\n")
        elif self.dots:
            self.stream.write(f"{self.GREEN}.{self.RESET}")
            self.stream.flush()

    def addError(self, test, err):
        super().addError(test, err)
        self.test_results.append(('ERROR', test))
        if self.showAll:
            self.stream.write(f"{self.RED}✗ ERROR{self.RESET}\n")
        elif self.dots:
            self.stream.write(f"{self.RED}E{self.RESET}")
            self.stream.flush()

    def addFailure(self, test, err):
        super().addFailure(test, err)
        self.test_results.append(('FAIL', test))
        if self.showAll:
            self.stream.write(f"{self.RED}✗ FAIL{self.RESET}\n")
        elif self.dots:
            self.stream.write(f"{self.RED}F{self.RESET}")
            self.stream.flush()

    def addSkip(self, test, reason):
        super().addSkip(test, reason)
        self.test_results.append(('SKIP', test))
        if self.showAll:
            self.stream.write(f"{self.YELLOW}⊘ SKIP{self.RESET}\n")
        elif self.dots:
            self.stream.write(f"{self.YELLOW}s{self.RESET}")
            self.stream.flush()


class ColoredTextTestRunner(unittest.TextTestRunner):
    """Custom test runner with colored output"""
    resultclass = ColoredTextTestResult


def discover_tests(test_dir='tests'):
    """Discover all test files in the tests directory"""
    loader = unittest.TestLoader()
    start_dir = test_dir
    pattern = 'test_*.py'

    suite = loader.discover(start_dir, pattern=pattern)
    return suite


def run_specific_suite(suite_name):
    """Run a specific test suite"""
    loader = unittest.TestLoader()

    suite_map = {
        'config': 'tests.test_config_validation',
        'features': 'tests.test_scraper_features',
        'integration': 'tests.test_integration'
    }

    if suite_name not in suite_map:
        print(f"Unknown test suite: {suite_name}")
        print(f"Available suites: {', '.join(suite_map.keys())}")
        return None

    module_name = suite_map[suite_name]
    try:
        suite = loader.loadTestsFromName(module_name)
        return suite
    except Exception as e:
        print(f"Error loading test suite '{suite_name}': {e}")
        return None


def print_summary(result):
    """Print a detailed test summary"""
    total = result.testsRun
    passed = total - len(result.failures) - len(result.errors) - len(result.skipped)
    failed = len(result.failures)
    errors = len(result.errors)
    skipped = len(result.skipped)

    print("\n" + "="*70)
    print("TEST SUMMARY")
    print("="*70)

    # Overall stats
    print(f"\n{ColoredTextTestResult.BOLD}Total Tests:{ColoredTextTestResult.RESET} {total}")
    print(f"{ColoredTextTestResult.GREEN}✓ Passed:{ColoredTextTestResult.RESET} {passed}")
    if failed > 0:
        print(f"{ColoredTextTestResult.RED}✗ Failed:{ColoredTextTestResult.RESET} {failed}")
    if errors > 0:
        print(f"{ColoredTextTestResult.RED}✗ Errors:{ColoredTextTestResult.RESET} {errors}")
    if skipped > 0:
        print(f"{ColoredTextTestResult.YELLOW}⊘ Skipped:{ColoredTextTestResult.RESET} {skipped}")

    # Success rate
    if total > 0:
        success_rate = (passed / total) * 100
        color = ColoredTextTestResult.GREEN if success_rate == 100 else \
                ColoredTextTestResult.YELLOW if success_rate >= 80 else \
                ColoredTextTestResult.RED
        print(f"\n{color}Success Rate: {success_rate:.1f}%{ColoredTextTestResult.RESET}")

    # Category breakdown
    if hasattr(result, 'test_results'):
        print(f"\n{ColoredTextTestResult.BOLD}Test Breakdown by Category:{ColoredTextTestResult.RESET}")

        categories = {}
        for status, test in result.test_results:
            test_name = str(test)
            # Extract test class name
            if '.' in test_name:
                class_name = test_name.split('.')[0].split()[-1]
                if class_name not in categories:
                    categories[class_name] = {'PASS': 0, 'FAIL': 0, 'ERROR': 0, 'SKIP': 0}
                categories[class_name][status] += 1

        for category, stats in sorted(categories.items()):
            total_cat = sum(stats.values())
            passed_cat = stats['PASS']
            print(f"  {category}: {passed_cat}/{total_cat} passed")

    print("\n" + "="*70)

    # Return status
    return failed == 0 and errors == 0


def main():
    """Main test runner"""
    import argparse

    parser = argparse.ArgumentParser(
        description='Run tests for Skill Jangler',
        formatter_class=argparse.RawDescriptionHelpFormatter
    )

    parser.add_argument('--suite', '-s', type=str,
                       help='Run specific test suite (config, features, integration)')
    parser.add_argument('--verbose', '-v', action='store_true',
                       help='Verbose output (show each test)')
    parser.add_argument('--quiet', '-q', action='store_true',
                       help='Quiet output (minimal output)')
    parser.add_argument('--failfast', '-f', action='store_true',
                       help='Stop on first failure')
    parser.add_argument('--list', '-l', action='store_true',
                       help='List all available tests')

    args = parser.parse_args()

    # Set verbosity
    verbosity = 1
    if args.verbose:
        verbosity = 2
    elif args.quiet:
        verbosity = 0

    print(f"\n{ColoredTextTestResult.BOLD}{'='*70}{ColoredTextTestResult.RESET}")
    print(f"{ColoredTextTestResult.BOLD}SKILL JANGLER TEST SUITE{ColoredTextTestResult.RESET}")
    print(f"{ColoredTextTestResult.BOLD}{'='*70}{ColoredTextTestResult.RESET}\n")

    # Discover or load specific suite
    if args.suite:
        print(f"Running test suite: {ColoredTextTestResult.BLUE}{args.suite}{ColoredTextTestResult.RESET}\n")
        suite = run_specific_suite(args.suite)
        if suite is None:
            return 1
    else:
        print(f"Running {ColoredTextTestResult.BLUE}all tests{ColoredTextTestResult.RESET}\n")
        suite = discover_tests()

    # List tests
    if args.list:
        print("\nAvailable tests:\n")
        for test_group in suite:
            for test in test_group:
                print(f"  - {test}")
        print()
        return 0

    # Run tests
    runner = ColoredTextTestRunner(
        verbosity=verbosity,
        failfast=args.failfast
    )

    result = runner.run(suite)

    # Print summary
    success = print_summary(result)

    # Return appropriate exit code
    return 0 if success else 1


if __name__ == '__main__':
    sys.exit(main())
