import argparse
import os
import sys
from pathlib import Path

import pytest

from nrobo.cli.commands import clean, init
from nrobo.core import settings
from nrobo.helpers._pytest_helper import show_pytest_help
from nrobo.helpers.io_helper import copy_configs_if_updated
from nrobo.helpers.logging_helper import get_logger, set_logger_level
from nrobo.helpers.reporting_helper import prepare_reporting_args
from nrobo.utils.command_utils import initialize_project
from nrobo.version import __version__

logger = get_logger(name=settings.NROBO_APP)


def parse_nrobo_args(argv):
    parser = argparse.ArgumentParser(
        description=f"{settings.NROBO_APP} - Smart Test Runner built on Pytest",
        add_help=True,
        allow_abbrev=False,  # ⛔ Prevents "--co" from resolving to "--cov"
    )

    parser.add_argument(
        "--debug",
        action="store_true",
        default=False,
        help="Enable debug mode (prints verbose logs and sets NROBO_DEBUG=True)",  # noqa: E501
    )

    # known args
    parser.add_argument(
        "--suite",
        nargs="+",  # Accepts multiple values (space-separated)
        help="One or more suite YAML files under suites/ (space-separated or repeated).",  # noqa: E501
        default=None,
    )  # noqa: E501
    parser.add_argument(
        "--browser",
        action="store",
        help="Browser to run tests on (chrome, firefox, edge, etc.)",
        default=settings.DEFAULT_BROWSER,
    )
    parser.add_argument(
        "--no-headless",
        action="store_true",
        default=False,
        help="Run browser in headed mode (default is headless)",
    )
    parser.add_argument(
        "--init",
        action="store_true",
        help=f"Initialize a new {settings.NROBO_APP} project with sample suite and tests.",  # noqa: E501
    )
    parser.add_argument(
        "--coverage",
        action="store_true",
        default=False,
        help="Enable coverage reporting for the nRoBo framework. Used for nRobo framework coverage report!",
        # noqa: E501
    )

    parser.add_argument(
        '-v', '--version',
        action='version',
        version=f'nrobo version {__version__}'
    )

    if "--help" in sys.argv:
        logger.info(f"\n📜 {settings.NROBO_APP} Help Menu:")
        parser.print_help()

        try:
            user_input = (
                input(
                    f"\n❓ {settings.NROBO_APP} is backed by PyTest. Show PyTest options too? (y/n): "  # noqa: E501
                )  # noqa: E501
                .strip()
                .lower()
            )  # noqa: E501
        except EOFError:
            user_input = "n"  # fallback in non-interactive shells

        if user_input.startswith("y"):
            logger.info("\n📜 Pytest Help Menu:")
            show_pytest_help()

        raise SystemExit(0)

    return parser.parse_known_args()


def parse_subcommand(argv):
    parser = argparse.ArgumentParser(
        description="nrobo subcommands"
    )
    subparsers = parser.add_subparsers(dest="command", required=True)

    clean_parser = subparsers.add_parser("clean", help="Clean test_artifacts/")
    clean_parser.add_argument("-v", "--verbose", action="store_true")

    init_parser = subparsers.add_parser("init", help=f"{settings.NROBO_APP} project initializer")
    init_parser.add_argument('--app', required=True, type=str, help='App name (used as project name)')

    return parser.parse_args(argv)


def get_nrobo_arg_parser():

    if len(sys.argv) > 1 and sys.argv[1] in ["clean", "init"]:
        # Run subcommand parser only
        sub_args = parse_subcommand(sys.argv[1:])
        if sub_args.command == "clean":
            clean.run(sys.argv[2:])
        elif sub_args.command == "init":
            init.run(sys.argv[2:])

        sys.exit(0)

    args, unknown_args = parse_nrobo_args(sys.argv[1:])

    # Handle `nrobo --init`
    if args.init:
        initialize_project()
        sys.exit(0)

    try:
        copy_configs_if_updated()
    except FileNotFoundError:
        pass

    # Handle test execution
    suites = args.suite
    browser = args.browser

    if args.debug:
        os.environ["NROBO_DEBUG"] = "True"
        settings.DEBUG = True
        set_logger_level(logger=logger, stream_level=10, file_level=10)
    else:
        os.environ["NROBO_DEBUG"] = "False"
        settings.DEBUG = False

    # update args
    os.environ["NROBO_BROWSER"] = browser

    os.environ["NROBO_HEADLESS"] = str(not args.no_headless)

    if args.coverage:
        unknown_args.extend(
            [
                "--cov=nrobo",  # measure coverage for your framework package
                "--cov-report=html",
                "--cov-report=xml",  # generate HTML report
                "--cov-report=term-missing",  # show missing lines in terminal
                "--cov-fail-under=90",  # fail if coverage < 90%
            ]
        )

    # always change temp dir under project dir
    if not any("--basetemp=" in arg for arg in unknown_args):
        if settings.NROBO_BASENAME_TMP:
            unknown_args.extend(["--basetemp=.pytest_tmp"])

    unknown_args = prepare_reporting_args(pytest_args=unknown_args)
    logger.debug(f"Final PyTest Options=>{unknown_args}")
    return suites, browser, args, unknown_args


def check_if_nrobo_initialized():
    markers = [
        Path(settings.CONFIGS),
        Path(settings.TESTS_DIR),
        Path(settings.SUITES_DIR),
        Path("common") / "helpers",
        Path("common") / "utils",
    ]

    # Allowed commands that don't need full project
    bypass_keywords = ["init", "--help", "-h", "--version", "-v"]

    if any(not m.exists() for m in markers):
        if not any(bypass in sys.argv for bypass in bypass_keywords):
            print(f"🚫 {settings.NROBO_APP} project not initialized.")
            print("💡 Run this to get started:")
            print("    nrobo init --app my_project")
            sys.exit(1)
