import argparse
import os
import sys
import tempfile
from pytest_cream.fetch import fetch_tests
from pytest_cream.run import run_tests
from pytest_cream.filter import filter_tests
from pytest_cream import workflow


def main():
    parser = argparse.ArgumentParser(description="Quick Tester CLI")
    subparsers = parser.add_subparsers(dest="command")

    # Fetch command
    fetch_parser = subparsers.add_parser("fetch", help="Fetch tests from a branch")
    fetch_parser.add_argument(
        "--branch", required=True, help="Branch name to fetch tests from"
    )
    fetch_parser.add_argument(
        "--repo",
        default="bayesflow-org/bayesflow",
        help="Repo to fetch from (owner/repo or URL)",
    )

    # Run command
    run_parser = subparsers.add_parser("run", help="Run tests and log durations")
    run_parser.add_argument(
        "--output", default="test_durations.log", help="Output file for test durations"
    )
    run_parser.add_argument(
        "--tests-dir", default="tests", help="Directory containing tests"
    )

    # Filter command
    filter_parser = subparsers.add_parser(
        "filter", help="Filter tests based on duration"
    )
    filter_parser.add_argument(
        "--input", required=True, help="Input file with test durations"
    )
    filter_parser.add_argument(
        "--output", required=True, help="Output file for filtered tests"
    )
    filter_parser.add_argument(
        "--threshold", type=float, required=True, help="Duration threshold"
    )

    # Quick-run (full workflow)
    quick_parser = subparsers.add_parser(
        "quick-run",
        help="Fetch tests, run durations, run long tests then parallel short ones",
    )
    quick_parser.add_argument(
        "--repo",
        default="SermetPekin/quick-tester",
        help="Repo to fetch from (owner/repo or URL)",
    )
    quick_parser.add_argument("--branch", default="main", help="Branch to fetch")
    quick_parser.add_argument(
        "--threshold", type=float, default=0.5, help="Duration threshold in seconds"
    )
    quick_parser.add_argument(
        "--workers",
        type=int,
        default=4,
        help="Number of parallel workers for short tests",
    )
    quick_parser.add_argument(
        "--ws",
        "--workspace",
        dest="workspace",
        default=None,
        help="Directory to use as workspace for fetched tests and logs (keeps artifacts)",
    )
    quick_parser.add_argument(
        "--install-repo",
        dest="install_repo",
        default=None,
        help="Optional repo to install code from (owner/repo or URL). If provided, the installer will run before tests.",
    )
    quick_parser.add_argument(
        "--install-branch",
        dest="install_branch",
        default=None,
        help="Branch to install from (when --install-repo is provided).",
    )
    quick_parser.add_argument(
        "--install-mode",
        dest="install_mode",
        default="pip",
        choices=["pip", "editable", "wheel"],
        help="How to install the code from --install-repo: pip (default), editable (pip -e), or wheel",
    )
    quick_parser.add_argument(
        "--install-uv",
        dest="install_uv",
        action="store_true",
        help="Use uv instead of pip for package installs (avoids pip issues in broken venvs)",
    )
    quick_parser.add_argument(
        "--install-cmd",
        dest="install_cmd",
        default=None,
        help="Custom install command to run after cloning (e.g., 'uv sync --extra cpu', 'poetry install --extras dev'). Use semicolon to separate multiple commands to try in order. Overrides --install-mode when provided.",
    )
    quick_parser.add_argument(
        "--install-fallback",
        dest="install_fallback",
        action="store_true",
        help="If custom install command fails, fallback to standard installation mode instead of aborting.",
    )
    quick_parser.add_argument(
        "--exclude-tests",
        dest="exclude_tests",
        default=None,
        help="Comma-separated patterns of test files or directories to exclude (e.g., 'test_integration,tests/slow')",
    )
    quick_parser.add_argument(
        "--python",
        dest="python_executable",
        default=None,
        help="Python executable to use for running tests (e.g., 'python3.10', '/usr/bin/python3.10'). If not specified, uses the current Python interpreter.",
    )

    args = parser.parse_args()

    if args.command == "fetch":
        fetch_tests(branch=args.branch, repo=args.repo)
    elif args.command == "run":
        run_tests(output_file=args.output)
    elif args.command == "filter":
        filter_tests(
            input_file=args.input, output_file=args.output, threshold=args.threshold
        )
    elif args.command == "quick-run":
        # If workspace is provided, validate it upfront and fail fast if it's not usable.
        if args.workspace:
            try:
                # Try to create the workspace directory if missing
                os.makedirs(args.workspace, exist_ok=True)
                # Try creating and removing a temporary file to verify writability
                fd, tmpfile = tempfile.mkstemp(dir=args.workspace)
                os.close(fd)
                os.remove(tmpfile)
            except Exception as e:
                print(
                    f"Error: cannot use workspace '{args.workspace}': {e}",
                    file=sys.stderr,
                )
                sys.exit(2)

        # Parse exclude patterns if provided
        exclude_tests = []
        if args.exclude_tests:
            exclude_tests = [pattern.strip() for pattern in args.exclude_tests.split(",") if pattern.strip()]

        workflow.quick_run(
            repo_url=args.repo,
            branch=args.branch,
            workspace=args.workspace,
            install_repo=args.install_repo,
            install_branch=args.install_branch,
            install_mode=args.install_mode,
            install_cmd=args.install_cmd,
            install_fallback=args.install_fallback,
            exclude_tests=exclude_tests,
            threshold=args.threshold,
            workers=args.workers,
            python_executable=args.python_executable,
        )
    else:
        parser.print_help()
