"""
Unified CLI entry point for ``test-runner``.

Creates the DI container and dispatches to ``capture`` or ``validate``.

Usage::

    test-runner capture [OPTIONS]
    test-runner validate [OPTIONS]
"""

from __future__ import annotations

import argparse
import logging
import sys
from pathlib import Path


def _configure_logging(level_name: str) -> None:
    level = getattr(logging, level_name.upper(), logging.WARNING)
    logging.basicConfig(
        level=level,
        format="%(asctime)s.%(msecs)03d  %(levelname)-8s  %(name)s  %(message)s",
        datefmt="%H:%M:%S",
    )


def _make_log_level_parser() -> argparse.ArgumentParser:
    """Shared parent parser that adds ``--log-level`` to every subcommand."""
    log_level_parser = argparse.ArgumentParser(add_help=False)
    log_level_parser.add_argument(
        "--log-level",
        default="WARNING",
        choices=["DEBUG", "INFO", "WARNING", "ERROR"],
        help="Set logging verbosity (default: WARNING)",
    )
    return log_level_parser


def main(argv: list[str] | None = None) -> None:
    """Unified CLI entry point with subcommands."""
    log_parent = _make_log_level_parser()

    parser = argparse.ArgumentParser(
        prog="test-runner",
        description="SCAI Code Verification -- capture and validate stored procedure baselines.",
        parents=[log_parent],
    )
    subparsers = parser.add_subparsers(dest="command", help="Available commands")

    capture_parser = subparsers.add_parser(
        "capture",
        help="Execute procedures on source and save baselines",
        parents=[log_parent],
    )
    _add_capture_args(capture_parser)

    validate_parser = subparsers.add_parser(
        "validate",
        help="Execute procedures on Snowflake and compare against baselines",
        parents=[log_parent],
        formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=36),
    )
    _add_validate_args(validate_parser)

    args = parser.parse_args(argv)
    _configure_logging(args.log_level)

    if args.command is None:
        parser.print_help()
        sys.exit(1)

    if args.command == "capture":
        _run_capture(args)
    elif args.command == "validate":
        _run_validate(args)


# ---------------------------------------------------------------------------
# Capture
# ---------------------------------------------------------------------------

def _add_capture_args(parser: argparse.ArgumentParser) -> None:
    parser.add_argument("--project-root", type=Path, default=Path.cwd())
    parser.add_argument("--source-connection", type=str, default=None)
    parser.add_argument("--baseline-dir", type=Path, default=None)
    parser.add_argument("-c", "--connection", type=str, default=None, dest="snowflake_connection")
    parser.add_argument("-w", "--watch", action="store_true", default=False)
    parser.add_argument("-q", "--quiet", action="store_true", default=False)
    parser.add_argument(
        "--workers", type=int, default=1,
        help="Number of parallel workers (default: 1 = sequential)",
    )
    parser.add_argument(
        "--where", type=str, default=None,
        help="SQL-like WHERE clause to filter code units (same syntax as 'scai code deploy --where')",
    )
    parser.add_argument(
        "--include-dependencies", action="store_true", default=False,
        help="When used with --where, also include dependencies of matched code units",
    )


def _run_capture(args: argparse.Namespace) -> None:
    from test_runner.common.container import create_container
    from test_runner.capture.runner import run_capture

    try:
        container = create_container(
            str(args.project_root),
            source_connection=args.source_connection,
            target_connection=args.snowflake_connection,
        )
        stats = run_capture(
            config=container.config(),
            factory_registry=container.factory_registry(),
            project_root=args.project_root,
            baseline_dir=args.baseline_dir,
            snowflake_connection=args.snowflake_connection,
            workers=args.workers,
            where=args.where,
            include_dependencies=args.include_dependencies,
        )
    except (FileNotFoundError, ValueError) as exc:
        print(f"Error: {exc}", file=sys.stderr)
        sys.exit(1)

    sys.exit(stats.failed)


# ---------------------------------------------------------------------------
# Validate
# ---------------------------------------------------------------------------

def _add_validate_args(parser: argparse.ArgumentParser) -> None:
    parser.add_argument("--project-root", type=Path, default=Path.cwd())
    parser.add_argument("-c", "--connection", type=str, default=None, dest="snowflake_connection")
    parser.add_argument("--baseline-dir", type=Path, default=None)
    parser.add_argument("--baseline-stage", type=str, default=None)
    parser.add_argument(
        "--where", type=str, default=None,
        help="SQL-like WHERE clause to filter code units (same syntax as 'scai code deploy --where')",
    )
    parser.add_argument(
        "--include-dependencies", action="store_true", default=False,
        help="When used with --where, also include dependencies of matched code units",
    )
    parser.add_argument("--create-schema", action="store_true", default=False)
    parser.add_argument("-w", "--watch", action="store_true", default=False)
    parser.add_argument("-q", "--quiet", action="store_true", default=False)
    parser.add_argument(
        "--output-dir",
        type=Path,
        default=None,
        metavar="DIR",
        help="Write local result files to DIR (default: off; results go to Snowflake)",
    )
    parser.add_argument(
        "--dump-baseline-and-actual", action="store_true", default=False,
        help="Write per-case baseline/actual row dumps inside --output-dir",
    )
    parser.add_argument(
        "--workers", type=int, default=1,
        help="Number of parallel workers (default: 1 = sequential)",
    )


def _run_validate(args: argparse.Namespace) -> None:
    from test_runner.common.container import create_container
    from test_runner.validate.runner import run_validate

    output_dir = args.output_dir

    try:
        container = create_container(
            str(args.project_root),
            target_connection=args.snowflake_connection,
        )
        stats = run_validate(
            config=container.config(),
            factory_registry=container.factory_registry(),
            project_root=args.project_root,
            snowflake_connection=args.snowflake_connection,
            baseline_dir=args.baseline_dir,
            baseline_stage=args.baseline_stage,
            where=args.where,
            include_dependencies=args.include_dependencies,
            create_schema=args.create_schema,
            output_dir=output_dir,
            dump_baseline_and_actual=args.dump_baseline_and_actual,
            workers=args.workers,
        )
    except (FileNotFoundError, ValueError) as exc:
        print(f"Error: {exc}", file=sys.stderr)
        sys.exit(1)

    sys.exit(stats.failed + stats.errors)


if __name__ == "__main__":
    main()
