"""Command line interface for pypack."""

from __future__ import annotations

import argparse
import asyncio
import logging
import platform
import time
from pathlib import Path

from pytola.core.logger import get_logger

from ..core.config import (
    ArchiveFormat,
    ConfigFactory,
    LoaderType,
    MirrorSource,
    WorkflowConfig,
)
from ..core.workflow import (
    PackageWorkflow,
    StandardCleaningStrategy,
)

logger = get_logger(__name__)

cwd = Path.cwd()
is_windows = platform.system() == "Windows"
ext = ".exe" if is_windows else ""

__version__ = "1.0.0"
__build__ = "20260120"


def parse_args() -> argparse.Namespace:
    """Parse command line arguments using subcommand structure.

    Returns
    -------
        Parsed arguments namespace
    """
    parser = argparse.ArgumentParser(
        prog="pyp",
        description="Python packaging tool with workflow orchestration",
    )

    # Add common arguments to parent parser
    parent_parser = argparse.ArgumentParser(add_help=False)
    parent_parser.add_argument("--debug", "-d", action="store_true", help="Debug mode")

    # Create subparsers
    subparsers = parser.add_subparsers(
        dest="command",
        required=True,
        metavar="",  # Hide the default 'subcommands' text
        help="Available commands",
    )

    # Run subcommand
    run_parser = subparsers.add_parser(
        "run",
        aliases=["r"],
        help="Run the packaged application",
        parents=[parent_parser],
    )
    run_parser.add_argument(
        "project",
        type=str,
        nargs="?",
        help="Project or executable name (e.g., 'docscan' or 'docscan-gui')",
    )
    run_parser.add_argument(
        "args",
        type=str,
        nargs="*",
        help="Additional arguments to pass to the project",
    )

    # Build subcommand
    build_parser = subparsers.add_parser(
        "build",
        aliases=["b"],
        help="Build the project",
        parents=[parent_parser],
    )

    # Clean subcommand
    subparsers.add_parser(
        "clean",
        aliases=["c"],
        help="Clean build artifacts",
        parents=[parent_parser],
    )

    # List subcommand
    subparsers.add_parser(
        "list",
        aliases=["l"],
        help="List available projects",
        parents=[parent_parser],
    )

    # Version subcommand
    subparsers.add_parser(
        "version",
        aliases=["v"],
        help="Show version information",
        parents=[parent_parser],
    )
    build_parser.add_argument(
        "--python-version",
        type=str,
        default="3.8.10",
        help="Python version to install",
    )
    build_parser.add_argument(
        "--loader-type",
        type=str,
        choices=[lt.value for lt in LoaderType],
        default=LoaderType.CONSOLE.value,
        help="Loader type",
    )
    build_parser.add_argument(
        "--entry-suffix",
        type=str,
        default=".ent",
        help="Entry file suffix (default: .ent, alternatives: .py)",
    )
    build_parser.add_argument(
        "--no-loader",
        action="store_true",
        help="Skip loader generation",
    )
    build_parser.add_argument(
        "-o",
        "--offline",
        action="store_true",
        help="Offline mode",
    )
    build_parser.add_argument(
        "-j",
        "--jobs",
        type=int,
        default=4,
        help="Maximum concurrent tasks",
    )

    # Library packing arguments (build-specific)
    build_parser.add_argument(
        "--cache-dir",
        type=str,
        default=None,
        help="Custom cache directory for dependencies",
    )
    build_parser.add_argument(
        "--archive-format",
        type=str,
        choices=[af.value for af in ArchiveFormat],
        default=ArchiveFormat.ZIP.value,
        help="Archive format for dependencies",
    )
    build_parser.add_argument(
        "--mirror",
        type=str,
        default=MirrorSource.ALIYUN.value,
        choices=[ms.value for ms in MirrorSource],
        help="PyPI mirror source for faster downloads",
    )

    # Archive options (optional post-build step)
    build_parser.add_argument(
        "--archive",
        "-a",
        type=str,
        nargs="?",
        const="zip",
        default=None,
        choices=["zip", "tar", "gztar", "bztar", "xztar", "7z", "nsis"],
        help="Create archive after build (default format: zip if flag used)",
    )

    return parser.parse_args()


async def _run_command_async(config: WorkflowConfig, command: str) -> None:
    """Run async commands."""
    workflow = PackageWorkflow(
        root_dir=config.directory,
        config=config,
        cleaning_strategy=StandardCleaningStrategy(),
    )
    if command == "build":
        await workflow.build()
    elif command == "clean":
        workflow.clean_project()
    elif command == "list":
        workflow.list_projects()
    else:
        msg = f"Unknown command: {command}"
        raise ValueError(msg)


def main() -> None:
    """Run main entry point for package workflow tool using factory pattern."""
    args = parse_args()

    # Build workflow configuration using factory pattern
    config = ConfigFactory.create_from_args(args, cwd)

    workflow = PackageWorkflow(
        root_dir=config.directory,
        config=config,
        cleaning_strategy=StandardCleaningStrategy(),
    )

    # Command dispatch using pattern matching
    command = args.command

    # Configure logging level with enhanced debug information
    if args.debug:
        logger.setLevel(logging.DEBUG)
        logger.debug("==================================================")
        logger.debug("DEBUG MODE ENABLED - Enhanced Diagnostics")
        logger.debug("==================================================")
        logger.debug(f"Command: {command}")
        logger.debug(f"Working directory: {cwd}")
        logger.debug(f"Arguments: {vars(args)}")
        logger.debug(f"Platform: {platform.system()} {platform.release()}")
        logger.debug(f"Python version: {platform.python_version()}")
        logger.debug("==================================================")

    if command in {"version", "v"}:
        logger.info(f"pyp {__version__} (build {__build__})")
        if args.debug:
            logger.debug(
                f"Version command executed at: {time.strftime('%Y-%m-%d %H:%M:%S')}",
            )
    elif command in {"list", "l", "ls"}:
        if args.debug:
            logger.debug("Starting project listing with enhanced debug info...")
        workflow.list_projects()
        if args.debug:
            logger.debug("Project listing completed")
    elif command in {"run", "r"}:
        if args.debug:
            logger.debug(f"Running project: {args.project}")
            logger.debug(f"Additional arguments: {args.args}")
        workflow.run_project(args.project, args.args)
    elif command in {"clean", "c"}:
        if args.debug:
            logger.debug("Starting cleanup process...")
        workflow.clean_project()
        if args.debug:
            logger.debug("Cleanup completed")
    elif command in {"build", "b"}:
        try:
            if args.debug:
                logger.debug("Starting build workflow execution...")
                logger.debug(f"Build configuration: {config}")
                start_time = time.perf_counter()

            asyncio.run(workflow.build())

            if args.debug:
                elapsed = time.perf_counter() - start_time
                logger.debug(f"Build workflow completed in {elapsed:.2f} seconds")
                logger.debug("==================================================")
                logger.debug("BUILD SUMMARY")
                logger.debug("==================================================")
                logger.debug(f"Root directory: {config.directory}")
                logger.debug(f"Project name: {config.project_name or 'Auto-detected'}")
                logger.debug(f"Python version: {config.python_version}")
                logger.debug(f"Loader type: {config.loader_type.value}")
                logger.debug(f"Offline mode: {config.offline}")
                logger.debug(f"Max concurrent jobs: {config.max_concurrent}")
                logger.debug(f"Mirror source: {config.mirror.value}")
                logger.debug("==================================================")

            logger.info("Packaging completed successfully!")
        except Exception as e:
            if args.debug:
                logger.debug(f"Build failed with exception: {type(e).__name__}: {e}")
                import traceback

                logger.debug("Stack trace:")
                logger.debug(traceback.format_exc())
            logger.exception(f"Packaging failed: {e}")
            raise


if __name__ == "__main__":
    main()
