"""Image deploy import logic: copy/move from a USB or upload-dir source
into ``SAMBA_SHARE/<image_type>/Deploy/`` while merging shared subdirs
(``Out-of-box Drivers`` etc.) into ``SAMBA_SHARE/_shared/`` and replacing
the per-image copies with symlinks. This is what lets two image types
re-use the same multi-GB driver tree without doubling disk usage.
"""

import os
import shutil

import config
from services.system import find_usb_mounts


def _replace_with_symlink(link_path, target_path):
    """Replace a file/dir/symlink at link_path with a symlink to target_path."""
    if os.path.islink(link_path):
        os.remove(link_path)
    elif os.path.isdir(link_path):
        shutil.rmtree(link_path)
    os.symlink(target_path, link_path)


def _merge_tree(src, dst, move=False):
    """Recursively merge src tree into dst, overwriting existing files.

    When move=True, files are moved instead of copied (saves disk space
    on imports from the local upload-dir).
    """
    _transfer = shutil.move if move else shutil.copy2
    _transfer_tree = shutil.move if move else shutil.copytree
    for item in os.listdir(src):
        s = os.path.join(src, item)
        d = os.path.join(dst, item)
        if os.path.isdir(s):
            if os.path.isdir(d):
                _merge_tree(s, d, move=move)
            else:
                if os.path.exists(d):
                    os.remove(d)
                _transfer_tree(s, d)
        else:
            os.makedirs(os.path.dirname(d), exist_ok=True)
            _transfer(s, d)


def import_deploy(src_deploy, dst_deploy, target="", move=False):
    """Import Deploy/ contents, redirecting shared subdirs into _shared/."""
    scoped_shared = []
    prefix_key = ""
    for prefix, dirs in config.SHARED_DEPLOY_SCOPED.items():
        if target.startswith(prefix):
            scoped_shared = dirs
            prefix_key = prefix
            break

    _transfer = shutil.move if move else shutil.copy2
    _transfer_tree = shutil.move if move else shutil.copytree

    os.makedirs(dst_deploy, exist_ok=True)
    for item in os.listdir(src_deploy):
        src_item = os.path.join(src_deploy, item)
        dst_item = os.path.join(dst_deploy, item)

        if not os.path.isdir(src_item):
            _transfer(src_item, dst_item)
            continue

        if item in config.SHARED_DEPLOY_GLOBAL:
            shared_dest = os.path.join(config.SHARED_DIR, item)
            os.makedirs(shared_dest, exist_ok=True)
            _merge_tree(src_item, shared_dest, move=move)
            _replace_with_symlink(dst_item, shared_dest)
            continue

        if item in scoped_shared:
            shared_dest = os.path.join(config.SHARED_DIR, f"{prefix_key}{item}")
            os.makedirs(shared_dest, exist_ok=True)
            _merge_tree(src_item, shared_dest, move=move)
            _replace_with_symlink(dst_item, shared_dest)
            continue

        if os.path.isdir(dst_item):
            _merge_tree(src_item, dst_item, move=move)
        else:
            _transfer_tree(src_item, dst_item)


def allowed_import_source(source):
    """True if source is a USB mount or under the upload dir."""
    usb = find_usb_mounts()
    if any(source == m or source.startswith(m + "/") for m in usb):
        return True
    if source == config.UPLOAD_DIR or source.startswith(config.UPLOAD_DIR + "/"):
        return os.path.isdir(source)
    return False
