#!/usr/bin/env python3
"""
Recursively copy a folder to a destination, excluding hidden files and folders.

This script copies all files and subfolders from a source directory to a destination directory,
skipping any hidden files or folders (those starting with a dot).

Usage:
    ./copy_folder.py SOURCE DESTINATION

Arguments:
    SOURCE      Path to the source folder to copy from.
    DESTINATION Path to the destination folder to copy to.

Example:
    ./copy_folder.py ~/my_project ~/backup/my_project

Notes:
    - Hidden files/folders (starting with a dot) are excluded.
    - The destination folder will be created if it does not exist.
    - Existing files in the destination will be overwritten.
"""

import argparse
import os
import shutil
from pathlib import Path

def copy_folder_excluding_hidden(src, dst):
    """Recursively copy src to dst, excluding hidden files and folders."""
    src_path = Path(src)
    dst_path = Path(dst)

    if not src_path.exists():
        raise FileNotFoundError(f"Source folder does not exist: {src_path}")

    if not dst_path.exists():
        dst_path.mkdir(parents=True, exist_ok=True)

    for item in src_path.iterdir():
        if item.name.startswith('.'):
            continue  # Skip hidden files/folders
        if item.is_dir():
            shutil.copytree(item, dst_path / item.name, ignore=shutil.ignore_patterns('.*'))
        else:
            shutil.copy2(item, dst_path / item.name)

def main():
    parser = argparse.ArgumentParser(
        description="Recursively copy a folder, excluding hidden files and folders."
    )
    parser.add_argument(
        "source",
        type=str,
        help="Source folder to copy from."
    )
    parser.add_argument(
        "destination",
        type=str,
        help="Destination folder to copy to."
    )

    args = parser.parse_args()

    try:
        copy_folder_excluding_hidden(args.source, args.destination)
        print(f"Successfully copied from {args.source} to {args.destination}")
    except Exception as e:
        print(f"Error: {e}")
        exit(1)

if __name__ == "__main__":
    main()
