"""Runs pytest, coverage, linters, and security checks."""

import os
import subprocess  # nosec
import sys


def get_modified_files_as_set():
    """Get a set of modified files in the current git branch."""
    # Run the git command
    result = subprocess.run(  # nosec
        ["git", "diff", "--name-only", "HEAD"],
        capture_output=True,  # Redirect stdout/stderr
        text=True,  # Decode output to string
        check=False,
    )

    # Strip whitespace and split on newlines
    file_list = result.stdout.strip().split("\n")
    # Remove "pyproject.toml" from the list
    file_list = [f for f in file_list if f != "pyproject.toml"]

    # Convert to a set (filter out any empty strings that might occur)
    modified_files = {f for f in file_list if f}

    return modified_files


def run_coverage():
    """
    Run coverage against all files in the `src` directory
    and output an XML report to `reports/coverage.xml`.
    """
    # Set environment to skip integration tests by default
    env = os.environ.copy()
    if "INTEGRATION_TEST_ENABLE" not in env:
        env["INTEGRATION_TEST_ENABLE"] = "false"

    # 1. Run pytest with coverage, using `src` as the source
    subprocess.run(["coverage", "run", "--source=src", "-m", "pytest"], check=True, env=env)  # nosec

    # 2. Generate an XML coverage report in `reports/coverage.xml`
    subprocess.run(["coverage", "xml", "-o", "reports/coverage/coverage.xml"], check=True)  # nosec

    print("Coverage completed. XML report generated at reports/coverage.xml.")


def run_tests():
    """Runs pytests against tests in the `tests` directory."""
    # Set environment to skip integration tests by default
    env = os.environ.copy()
    if "INTEGRATION_TEST_ENABLE" not in env:
        env["INTEGRATION_TEST_ENABLE"] = "false"

    subprocess.run(["pytest", "tests"], check=True, env=env)  # nosec


def run_lint_all():
    """Run linters: ruff format, ruff check, mypy, and bandit."""
    failures = []

    # 1. Auto-format with ruff
    result = subprocess.run(["ruff", "format", "src", "tests"], check=False)  # nosec
    if result.returncode != 0:
        failures.append("ruff format")

    # 2. Auto-fix with ruff check
    result = subprocess.run(["ruff", "check", "--fix", "src", "tests"], check=False)  # nosec
    if result.returncode != 0:
        failures.append("ruff check --fix")

    # 3. Strict ruff check (no fixes, just report)
    result = subprocess.run(["ruff", "check", "src", "tests"], check=False)  # nosec
    if result.returncode != 0:
        failures.append("ruff check")

    # 4. Type checking with mypy
    result = subprocess.run(["mypy", "src/tql/"], check=False)  # nosec
    if result.returncode != 0:
        failures.append("mypy")

    # 5. Security checks with bandit
    result = subprocess.run(["bandit", "-c", "bandit.yml", "-r", "src"], check=False)  # nosec
    if result.returncode != 0:
        failures.append("bandit")

    if failures:
        print(f"\nLinting failures: {', '.join(failures)}")
        sys.exit(1)
    else:
        print("\nAll linting checks passed.")


def run_lint():
    """Run ruff format and ruff check on modified git files."""
    files = get_modified_files_as_set()
    files_list = list(files)

    if not files_list:
        print("No modified files detected.")
        return

    subprocess.run(["ruff", "format", *files_list], check=False)  # nosec
    subprocess.run(["ruff", "check", "--fix", *files_list], check=False)  # nosec
    subprocess.run(["ruff", "check", *files_list], check=False)  # nosec


def run_badge():
    """Generate a badge using genbadge."""
    # Set environment to skip integration tests by default
    env = os.environ.copy()
    if "INTEGRATION_TEST_ENABLE" not in env:
        env["INTEGRATION_TEST_ENABLE"] = "false"

    subprocess.run(  # nosec
        [
            "coverage",
            "run",
            "--source=src",
            "-m",
            "pytest",
            "--junit-xml=reports/junit/junit.xml",
        ],
        check=True,
        env=env,
    )

    # 2. Generate an XML coverage report in `reports/coverage.xml`
    subprocess.run(["coverage", "xml", "-o", "reports/coverage/coverage.xml"], check=True)  # nosec

    # 3. Generate badge for coverage
    subprocess.run(["genbadge", "coverage", "-o", "badge/coverage-badge.svg"], check=True)  # nosec

    # 4. Generate badge for tests
    subprocess.run(  # nosec
        ["genbadge", "tests", "-t", "90", "-o", "badge/test-badge.svg"],
        check=True,
    )
