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

import sys
import unittest


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 Seeker",
        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 SEEKER 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())
