# copier.py
# Funções para copiar ficheiros para o destino organizado
from modules.organizer import (
    obter_data_ficheiro,
    criar_pasta_destino,
    categorizar_por_tipo,
)
from pathlib import Path
import shutil
from tqdm import tqdm
from concurrent.futures import ThreadPoolExecutor, as_completed
from modules.logger import logger
from collections.abc import Callable


def copiar_ficheiro_individual(
    ficheiro: str,
    base_destino: str,
    categorizar_data: bool = False,
    usar_criacao: bool = False,
    formato_data: str = "%Y-%m-%d",
) -> None:
    """copiar um ficheiro para o destino indicado,
    com base nos parametros passados

    argumentos:
    ficheiro (str) -> caminho (como str) do ficheiro a ser copiado
    base_destino (str) -> directório de destino para onde será copiado o ficheiro
    categorizar_data (bool) -> flag para activar categorização por data (defeito: False)
    usar_criacao (bool) -> usar data de criação (defeito: False usar data de modificacao)
    formato_data (str) -> formato de data para nome dos subdirectórios (defeito: '%d-%m-%Y')

    retorna:
    None
    """
    try:
        ficheiro_path = Path(ficheiro)
        if not ficheiro_path.exists():
            logger.warning(
                "Ficheiro '%s' não encontrado. A ignorar.", ficheiro)
            return
        if categorizar_data:
            data_ficheiro = obter_data_ficheiro(
                ficheiro, usar_criacao=usar_criacao)
            pasta_destino = criar_pasta_destino(
                str(base_destino),
                categorizar_por_tipo(ficheiro),
                data_ficheiro,
                formato_data,
            )
        else:
            pasta_destino = criar_pasta_destino(
                str(base_destino), categorizar_por_tipo(ficheiro)
            )
        destino_ficheiro = pasta_destino / ficheiro_path.name
        shutil.copy2(ficheiro_path, destino_ficheiro)
    except Exception as e:
        logger.error("Erro a copiar '%s': %s", Path(ficheiro).name, e)


def copiar_ficheiros_para_destino(
    lista_ficheiros: list[str],
    base_destino: str,
    categorizar_data: bool = False,
    usar_criacao: bool = False,
    formato_data: str = "%Y-%m-%d",
    usar_threads: bool = True,
    max_workers: int = 8,
    progresso_callback: Callable | None = None,
) -> None:
    """
    Copiar cada ficheiro na lista para o directório base, seguindo as regras de categorização

    argumentos:
    lista_ficheiros (list[str]) -> lista com o caminho dos ficheiros a serem copiados
    base_destino (str) -> directorio base no qual serão criados os novos directórios com base nas regras de categorização
    categorizar_data (bool) -> flag para activar categorização por data (defeito: False)
    usar_criacao (bool) -> usar data de criação (defeito: False usar data de modificacao)
    formato_data (str) -> formato de data para nome dos subdirectórios (defeito: '%d-%m-%Y')

    retorna:
    None
    """
    if usar_threads:
        with ThreadPoolExecutor(max_workers=max_workers) as executor:
            futures = [
                executor.submit(
                    copiar_ficheiro_individual,
                    ficheiro,
                    base_destino,
                    categorizar_data,
                    usar_criacao,
                    formato_data,
                )
                for ficheiro in lista_ficheiros
            ]

            for _ in as_completed(futures):
                if progresso_callback:
                    progresso_callback()

            # codigo comentado para integrar a funcionalidade na interface gui
            # for _ in tqdm(
            #     as_completed(futures),
            #     total=len(futures),
            #     desc="A copiar ficheiros ",
            #     unit="ficheiro ",
            # ):
            #     pass
    else:
        for ficheiro in tqdm(
            lista_ficheiros, desc="A copiar ficheiros ", unit="ficheiro "
        ):
            copiar_ficheiro_individual(
                ficheiro, base_destino, categorizar_data, usar_criacao, formato_data
            )
