"""
Regression Test Runner for Genesis System.

This script executes unit, integration, and contract tests,
reports pass/fail status, coverage, and duration, and blocks
deployment on failure.
"""

import argparse
import logging
import os
import subprocess
import sys
import time
from typing import List, Tuple

# Configure logging
logging.basicConfig(
    level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)

# Constants
UNIT_TEST_COMMAND = ["pytest", "tests/unit"]
INTEGRATION_TEST_COMMAND = ["pytest", "tests/integration"]
CONTRACT_TEST_COMMAND = ["pytest", "tests/contract"]
COVERAGE_COMMAND = ["coverage", "report", "-m"]


class TestResult:
    """
    Represents the result of a test run.
    """

    def __init__(self, name: str, passed: bool, duration: float, output: str):
        """
        Initializes a TestResult object.

        Args:
            name: The name of the test suite.
            passed: True if the tests passed, False otherwise.
            duration: The duration of the test run in seconds.
            output: The output of the test run.
        """
        self.name = name
        self.passed = passed
        self.duration = duration
        self.output = output

    def __str__(self) -> str:
        """
        Returns a string representation of the TestResult.

        Returns:
            A string representing the TestResult.
        """
        return (
            f"Test Suite: {self.name}\n"
            f"Passed: {self.passed}\n"
            f"Duration: {self.duration:.2f} seconds\n"
            f"Output:\n{self.output}\n"
        )


def run_test_suite(command: List[str], name: str) -> TestResult:
    """
    Runs a test suite using the given command.

    Args:
        command: The command to execute the test suite.
        name: The name of the test suite.

    Returns:
        A TestResult object representing the result of the test run.
    """
    start_time = time.time()
    try:
        process = subprocess.run(
            command, capture_output=True, text=True, check=True
        )
        end_time = time.time()
        duration = end_time - start_time
        passed = True
        output = process.stdout
        logging.info(f"{name} tests completed successfully.")
    except subprocess.CalledProcessError as e:
        end_time = time.time()
        duration = end_time - start_time
        passed = False
        output = e.stderr
        logging.error(f"{name} tests failed: {e}")
    except FileNotFoundError as e:
        end_time = time.time()
        duration = end_time - start_time
        passed = False
        output = str(e)
        logging.error(f"Command not found: {e}")
    except Exception as e:
        end_time = time.time()
        duration = end_time - start_time
        passed = False
        output = str(e)
        logging.exception(f"An unexpected error occurred: {e}")
        
    return TestResult(name, passed, duration, output)


def run_coverage() -> Tuple[bool, str]:
    """
    Runs coverage and returns the report.

    Returns:
        A tuple containing:
            - A boolean indicating whether the coverage check passed (True) or failed (False).
            - The coverage report as a string.
    """
    try:
        process = subprocess.run(
            COVERAGE_COMMAND, capture_output=True, text=True, check=True
        )
        report = process.stdout
        logging.info("Coverage check completed successfully.")
        return True, report
    except subprocess.CalledProcessError as e:
        logging.error(f"Coverage check failed: {e}")
        return False, e.stderr
    except FileNotFoundError as e:
        logging.error(f"Coverage command not found: {e}")
        return False, str(e)
    except Exception as e:
        logging.exception(f"An unexpected error occurred during coverage: {e}")
        return False, str(e)


def main() -> None:
    """
    Main function to run regression tests.
    """
    logging.info("Starting regression tests...")

    unit_test_result = run_test_suite(UNIT_TEST_COMMAND, "Unit Tests")
    integration_test_result = run_test_suite(
        INTEGRATION_TEST_COMMAND, "Integration Tests"
    )
    contract_test_result = run_test_suite(CONTRACT_TEST_COMMAND, "Contract Tests")

    coverage_passed, coverage_report = run_coverage()

    all_tests_passed = (
        unit_test_result.passed
        and integration_test_result.passed
        and contract_test_result.passed
        and coverage_passed
    )

    print("--- Test Results ---")
    print(unit_test_result)
    print(integration_test_result)
    print(contract_test_result)
    print("--- Coverage Report ---")
    print(coverage_report)

    if all_tests_passed:
        logging.info("All regression tests passed.")
        sys.exit(0)  # Exit with success code
    else:
        logging.error("Regression tests failed. Blocking deployment.")
        sys.exit(1)  # Exit with failure code


if __name__ == "__main__":
    main()
