"""Command-line interface for electron-angle-patcher."""

from __future__ import annotations

import argparse
import logging
import sys
from pathlib import Path

from electron_angle_patcher import (
    ChromiumSettingsPatcher,
    Config,
    ElectronAnglePatcher,
    LocalStateScanner,
    PatchResult,
    __version__,
)

logger = logging.getLogger(__name__)


def parse_arguments(args: list[str] | None = None) -> argparse.Namespace:
    """Parse command-line arguments.

    Args:
        args: List of argument strings (uses sys.argv if None).

    Returns:
        Parsed arguments namespace.
    """
    parser = argparse.ArgumentParser(
        description="Patch Electron and Chrome applications to use OpenGL rendering",
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )

    parser.add_argument(
        "--app-path",
        type=lambda p: _expand_path_if_exists(p),
        help="Path to a specific application's Local State file",
    )
    parser.add_argument(
        "--app-name",
        help="Name of the application (used with --app-path)",
    )
    parser.add_argument(
        "--scan-dir",
        type=lambda p: _expand_path_if_exists(p),
        help="Additional directory to scan for Electron applications",
    )
    parser.add_argument(
        "--list-only",
        action="store_true",
        help="Only list found applications without patching",
    )
    parser.add_argument(
        "--dry-run",
        action="store_true",
        help="Same as --list-only: show what would be patched without making changes",
    )
    parser.add_argument(
        "--deep-scan",
        action="store_true",
        help="Perform a deep scan of the user's home directory",
    )
    parser.add_argument(
        "--brave-path",
        type=lambda p: _expand_path_if_exists(p, default=Config.DEFAULT_BRAVE_PATH),
        default=Config.DEFAULT_BRAVE_PATH,
        help=f"Path to Brave Browser.app (default: {Config.DEFAULT_BRAVE_PATH})",
    )
    parser.add_argument(
        "--chrome-path",
        type=lambda p: _expand_path_if_exists(p, default=Config.DEFAULT_CHROME_PATH),
        default=Config.DEFAULT_CHROME_PATH,
        help=f"Path to Google Chrome.app (default: {Config.DEFAULT_CHROME_PATH})",
    )
    parser.add_argument(
        "--lghub-path",
        type=lambda p: _expand_path_if_exists(p, default=Config.DEFAULT_LGHUB_PATH),
        default=Config.DEFAULT_LGHUB_PATH,
        help=f"Path to lghub.app (default: {Config.DEFAULT_LGHUB_PATH})",
    )
    parser.add_argument(
        "-v", "--verbose",
        action="store_true",
        help="Enable verbose output",
    )
    parser.add_argument(
        "--version",
        action="version",
        version=f"%(prog)s {__version__}",
    )

    return parser.parse_args(args)


def _expand_path_if_exists(path_str: str, default=None) -> str | None:
    """Expand user path and return None if it doesn't exist.

    Args:
        path_str: Path string to expand.
        default: Default value to return if path doesn't exist.

    Returns:
        Expanded path string or default value.
    """
    from pathlib import Path

    expanded = Path(path_str).expanduser()
    if expanded.exists() or default is not None:
        return str(expanded)
    return path_str


def setup_logging(verbose: bool = False) -> None:
    """Configure logging for the application.

    Args:
        verbose: Enable DEBUG level logging if True, otherwise INFO.
    """
    level = logging.DEBUG if verbose else logging.INFO
    logging.basicConfig(
        level=level,
        format="%(message)s",
        handlers=[logging.StreamHandler()],
    )


def main(argv: list[str] | None = None) -> int:
    """Main entry point for the application.

    Args:
        argv: Command-line arguments (uses sys.argv if None).

    Returns:
        Exit code (0 for success, 1 for error, 130 for SIGINT).
    """
    import sys

    # Platform validation - only at runtime, not import time
    if sys.platform != "darwin":
        print("Error: This script only works on macOS", file=sys.stderr)
        return 1

    args = parse_arguments(argv)
    setup_logging(args.verbose)

    try:
        # Handle single app mode
        if args.app_path:
            app_name = args.app_name or "Custom application"
            if args.list_only or args.dry_run:
                logger.info("Found %s: %s", app_name, args.app_path)
            else:
                logger.info("Patching %s", app_name)
                patcher = ChromiumSettingsPatcher(Path(args.app_path))
                result = patcher.patch()
                return 0 if result == PatchResult.SUCCESS else 1

        # Handle custom directory scan mode
        if args.scan_dir:
            scan_path = Path(args.scan_dir)
            logger.info("Scanning custom directory: %s", scan_path)
            scanner = LocalStateScanner()
            apps = scanner.scan(scan_path)

            for app in apps:
                if args.list_only or args.dry_run:
                    logger.info("Found %s: %s", app.name, app.state_file)
                else:
                    logger.info("Patching %s", app.name)
                    patcher = ChromiumSettingsPatcher(app.state_file)
                    result = patcher.patch()
                    if result != PatchResult.SUCCESS:
                        logger.warning("Failed to patch %s", app.name)
            return 0

        # Run main patcher
        patcher = ElectronAnglePatcher(
            brave_path=args.brave_path,
            chrome_path=args.chrome_path,
            lghub_path=args.lghub_path,
        )
        list_only = args.list_only or args.dry_run
        summary = patcher.run(list_only=list_only, deep_scan=args.deep_scan)

        # Print summary if not list-only mode
        if not list_only and summary.total > 0:
            logger.info("")
            logger.info("=" * 50)
            logger.info("Patch Summary:")
            if summary.successful:
                logger.info("  Successfully patched: %d", len(summary.successful))
            if summary.already_patched:
                logger.info("  Already patched: %d", len(summary.already_patched))
            if summary.failed:
                logger.warning("  Failed: %d", len(summary.failed))
            logger.info("=" * 50)

        return 0

    except KeyboardInterrupt:
        logger.info("\nOperation cancelled by user")
        return 130
    except Exception as e:
        logger.exception("Unexpected error: %s", e)
        return 1


if __name__ == "__main__":
    sys.exit(main())
