# AUTOGENERATED! DO NOT EDIT! File to edit: ../../../../../../../../../Users/lukastk/dev/2025-11-09_00__repoyard/pts/mod/_utils/02_bisync_helper.pct.py.

# %% top_export
from pathlib import Path
import subprocess
from typing import Literal
from enum import Enum

from repoyard import const

# %% top_export
class SyncSetting(Enum):
    REPLACE_LOCAL = "replace_local"
    REPLACE_REMOTE = "replace_remote"
    BISYNC = "bisync"

# %% top_export
class _SyncError(Exception):
    def __init__(self, message: str, stdout: str, stderr: str):
        super().__init__(f"{message}\n\nrclone output:\n{stdout}\n{stderr}")
class Sync_RequiresForce(_SyncError): pass
class Sync_Conflict(_SyncError): pass
class Sync_Error(_SyncError): pass

def bisync_helper(
    rclone_config_path: str,
    sync_setting: SyncSetting,
    local_path: str,   
    remote: str,
    remote_path: str,
    force: bool,
    mkdir_if_missing: bool = True,
    include_path: Path|None = None,
    exclude_path: Path|None = None,
    filters_path: Path|None = None,
    include: list[str]|None = None,
    exclude: list[str]|None = None,
    filter: list[str]|None = None,
):
    """
    Helper to execute the standard routine for bisyncing a local and remote folder.
    """
    
    # AUTOGENERATED! DO NOT EDIT! File to edit: ../../../../../../../../../Users/lukastk/dev/2025-11-09_00__repoyard/pts/mod/_utils/02_bisync_helper.pct.py.
    
    # %% auto 0
    __all__ = ['remote_exists', 'remote_repo_is_dir']
    
    # %% ../../../../../../../../../Users/lukastk/dev/2025-11-09_00__repoyard/pts/mod/_utils/02_bisync_helper.pct.py 13
    from . import rclone_path_exists
    
    # If the remote folder does not exist, we must sync instead of bisync
    remote_exists, remote_repo_is_dir = rclone_path_exists(
        rclone_config_path=rclone_config_path,
        source=remote,
        source_path=remote_path,
    )
    
    if remote_exists and not remote_repo_is_dir:
        raise Exception(f"Remote folder '{remote_path}' is not a directory in remote {remote}.")
    
    # %% ../../../../../../../../../Users/lukastk/dev/2025-11-09_00__repoyard/pts/mod/_utils/02_bisync_helper.pct.py 14
    from . import rclone_bisync, rclone_sync, BisyncResult, rclone_mkdir, rclone_path_exists
    
    def _bisync(dry_run: bool, resync: bool, force: bool, return_command: bool=False) -> BisyncResult:
        return rclone_bisync(
            rclone_config_path=rclone_config_path,
            source="",
            source_path=local_path,
            dest=remote,
            dest_path=remote_path,
            include=include or [],
            exclude=exclude or [],
            filter=filter or [],
            include_file=include_path,
            exclude_file=exclude_path,
            filters_file=filters_path,
            dry_run=dry_run,
            resync=resync,
            force=force,
            return_command=return_command,
            verbose=False,
        )
        
    def _sync(dry_run: bool, source: str, source_path: str, dest: str, dest_path: str, return_command: bool=False,) -> BisyncResult:
        return rclone_sync(
            rclone_config_path=rclone_config_path,
            source=source,
            source_path=source_path,
            dest=dest,
            dest_path=dest_path,
            include=include or [],
            exclude=exclude or [],
            filter=filter or [],
            include_file=include_path,
            exclude_file=exclude_path,
            filters_file=filters_path,
            dry_run=dry_run,
            return_command=return_command,
            verbose=False,
        )
    
    # %% ../../../../../../../../../Users/lukastk/dev/2025-11-09_00__repoyard/pts/mod/_utils/02_bisync_helper.pct.py 15
    if mkdir_if_missing:
        rclone_mkdir(
            rclone_config_path=rclone_config_path,
            source="",
            source_path=local_path,
        )
        rclone_mkdir(
            rclone_config_path=rclone_config_path,
            source=remote,
            source_path=remote_path,
        )
    
    # %% ../../../../../../../../../Users/lukastk/dev/2025-11-09_00__repoyard/pts/mod/_utils/02_bisync_helper.pct.py 16
    if sync_setting == SyncSetting.BISYNC and remote_exists:
        # Dry run
        res_dry, stdout_dry, stderr_dry = _bisync(
            dry_run=True,
            resync=False,
            force=False,
        )
    
        res = None
        if BisyncResult.ERROR_NEEDS_RESYNC:
            res, stdout, stderr = _bisync(
                dry_run=False,
                resync=True,
                force=False,
            )
        elif BisyncResult.ERROR_ALL_FILES_CHANGED:
            if force:
                res_dry, stdout, stderr = _bisync(
                    dry_run=False,
                    resync=True,
                    force=True,
                )
            else:
                raise Sync_RequiresForce(f"All files in both local and remote have changed. Use `force=True` to force sync.", stdout_dry, stderr_dry)
        elif BisyncResult.CONFLICTS:
            raise Sync_Conflict(f"Conflicts found between local and remote.", stdout_dry, stderr_dry)
        elif BisyncResult.ERROR_OTHER:
            raise Sync_Error(f"Error.", stdout_dry, stderr_dry)
        elif BisyncResult.SUCCESS:
            res, stdout, stderr = _bisync(
                dry_run=False,
                resync=False,
                force=False,
            )
        else:
            raise ValueError(f"Unknown BisyncResult: {res_dry}")
    
        if res is not None:
            if res != BisyncResult.SUCCESS:
                raise Sync_Error(f"Error.", stdout, stderr)
            
    elif (sync_setting == SyncSetting.REPLACE_REMOTE or not remote_exists):
        res, stdout, stderr = _sync(
            dry_run=False,
            source="",
            source_path=local_path,
            dest=remote,
            dest_path=remote_path,
        )
        
        if not res:
            raise Sync_Error(f"Error.", stdout, stderr)
        
    elif sync_setting == SyncSetting.REPLACE_LOCAL:
        res, stdout, stderr = _sync(
            dry_run=False,
            source=remote,
            source_path=remote_path,
            dest="",
            dest_path=local_path,
        )
        
        if not res:
            raise Sync_Error(f"Error.", stdout, stderr)
    else:
        raise ValueError(f"Unknown sync setting: {sync_setting}")