Folder name created in archive will have every word start from a Capital Letter

import os
import shutil
import re
from datetime import datetime

# --- Konfiguracja Ścieżek ---
SOURCE_PATH = r"C:\wgrywanie\gotowe"
SOURCE_PATH_SECONDARY = r"C:\wgrywanie\nowe_przedmioty" # Dodatkowy folder do czyszczenia (teraz usuwa najstarsze pliki)
ARCHIVE_PATH_C = r"C:\wgrywanie\archiwum"
ARCHIVE_PATH_D = r"D:\archiwum" # Ścieżka do archiwum na pendrivie D:

# Dozwolone rozszerzenia plików graficznych (małe litery)
IMAGE_EXTENSIONS = ('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.heic', '.webp')

def get_longest_common_prefix(strings):
    """
    Znajduje najdłuższy wspólny prefiks w liście ciągów znaków.
    """
    if not strings:
        return ""
    if len(strings) == 1:
        return strings[0]

    strings.sort()
    first_str = strings[0]
    last_str = strings[-1]
    
    prefix = []
    for i in range(min(len(first_str), len(last_str))):
        if first_str[i] == last_str[i]:
            prefix.append(first_str[i])
        else:
            break
    return "".join(prefix)

def clean_folder_name(name):
    """
    Czyści nazwę folderu z niedozwolonych znaków i dostosowuje ją.
    """
    cleaned_name = re.sub(r'[^\w\-\s]', '', name)
    # Zastąp wiele podkreśleń, spacji lub myślników pojedynczą spacją, aby nazwa folderu nie zawierała "_"
    cleaned_name = re.sub(r'[_ -]+', ' ', cleaned_name).strip()
    
    if not cleaned_name:
        # Zaktualizowano nazwę zastępczą, aby nie zawierała podkreślenia
        cleaned_name = datetime.now().strftime("Archiwum %Y%m%d %H%M%S")
        print(f"Ostrzeżenie: Nie udało się ustalić czytelnej nazwy podfolderu z nazw plików. Użyto nazwy zastępczej: '{cleaned_name}'")
    
    return cleaned_name

def main():
    print("--- Skrypt przenoszenia zdjęć do archiwum ---")
    print(f"Główny folder źródłowy: {SOURCE_PATH}")
    print(f"Dodatkowy folder do czyszczenia: {SOURCE_PATH_SECONDARY}")
    print(f"Archiwum na C: {ARCHIVE_PATH_C}")
    print(f"Archiwum na D: {ARCHIVE_PATH_D}\n")

    # --- 1. Sprawdzenie folderu źródłowego ---
    if not os.path.exists(SOURCE_PATH):
        print(f"Błąd: Główny folder źródłowy '{SOURCE_PATH}' nie istnieje. Sprawdź ścieżkę i spróbuj ponownie.")
        input("Naciśnij Enter, aby zakończyć...")
        return

    # Sprawdzenie istnienia dodatkowego folderu do czyszczenia
    secondary_source_exists = False
    if os.path.exists(SOURCE_PATH_SECONDARY) and os.path.isdir(SOURCE_PATH_SECONDARY):
        secondary_source_exists = True
        print(f"Dodatkowy folder '{SOURCE_PATH_SECONDARY}' istnieje i z niego zostaną usunięte najstarsze zdjęcia (w liczbie przeniesionych do archiwum).")
    else:
        print(f"Ostrzeżenie: Dodatkowy folder do czyszczenia '{SOURCE_PATH_SECONDARY}' nie istnieje lub nie jest folderem. Usuwanie z niego zostanie pominięte.")
    print("")

    # --- 2. Pobranie plików zdjęć z głównego folderu źródłowego ---
    image_files = []
    try:
        for f in os.listdir(SOURCE_PATH):
            file_path = os.path.join(SOURCE_PATH, f)
            if os.path.isfile(file_path):
                if f.lower().endswith(IMAGE_EXTENSIONS):
                    image_files.append(f)
    except Exception as e:
        print(f"Błąd podczas listowania plików w folderze źródłowym: {e}")
        input("Naciśnij Enter, aby zakończyć...")
        return

    if not image_files:
        print(f"Brak zdjęć w folderze '{SOURCE_PATH}' do przeniesienia. Upewnij się, że są tam pliki graficzne (np. JPG, PNG, WEBP).")
        input("Naciśnij Enter, aby zakończyć...")
        return

    # --- 3. Określenie nazwy podfolderu (globalnej nazwy) ---
    base_names = [os.path.splitext(f)[0] for f in image_files]
    subfolder_name_raw = get_longest_common_prefix(base_names)

    if subfolder_name_raw:
        trimmed_name = subfolder_name_raw.rstrip('_-')
        if trimmed_name:
            subfolder_name = trimmed_name
        else:
            subfolder_name = base_names[0]
    else:
        subfolder_name = base_names[0]

    subfolder_name = clean_folder_name(subfolder_name)

    print(f"Ustalona nazwa podfolderu do archiwizacji: '{subfolder_name}'\n")

    # --- 4. Konstruowanie i tworzenie folderów docelowych ---
    dest_path_c = os.path.join(ARCHIVE_PATH_C, subfolder_name)
    dest_path_d = os.path.join(ARCHIVE_PATH_D, subfolder_name)

    usb_drive_present = False
    if os.path.exists(ARCHIVE_PATH_D) and os.path.isdir(ARCHIVE_PATH_D):
         usb_drive_present = True
    else:
        print(f"Ostrzeżenie: Pendrive (ścieżka '{ARCHIVE_PATH_D}') nie jest podłączony lub ścieżka jest nieprawidłowa. Kopiowanie na pendrive zostanie pominięte.")

    try:
        os.makedirs(dest_path_c, exist_ok=True)
        print(f"Folder na C: '{dest_path_c}' jest gotowy.")
    except Exception as e:
        print(f"Błąd podczas tworzenia folderu na C: '{dest_path_c}'. {e}")
        input("Naciśnij Enter, aby zakończyć...")
        return

    if usb_drive_present:
        try:
            os.makedirs(dest_path_d, exist_ok=True)
            print(f"Folder na D: '{dest_path_d}' jest gotowy.")
        except Exception as e:
            print(f"Błąd podczas tworzenia folderu na D: '{dest_path_d}'. {e}")
            usb_drive_present = False 

    print("")

    # --- 5. Przenoszenie i kopiowanie zdjęć ---
    moved_to_c = 0
    copied_to_d = 0
    failed_operations = []

    for filename in image_files:
        source_file_path = os.path.join(SOURCE_PATH, filename)
        dest_file_path_c = os.path.join(dest_path_c, filename)
        dest_file_path_d = os.path.join(dest_path_d, filename)

        print(f"Przetwarzanie: {filename}")

        file_moved_to_c_ok = False # Flaga sukcesu przeniesienia na C:
        file_copied_to_d_ok = False # Flaga sukcesu kopiowania na D:

        # Przenoszenie do C:
        try:
            shutil.move(source_file_path, dest_file_path_c)
            print(f"  -> Przeniesiono do C: '{dest_file_path_c}'")
            moved_to_c += 1
            file_moved_to_c_ok = True

            # Kopiowanie do D: (tylko jeśli przeniesienie do C: było udane i D: jest dostępne)
            if usb_drive_present:
                try:
                    shutil.copy2(dest_file_path_c, dest_file_path_d) # copy2 zachowuje metadane
                    print(f"  -> Skopiowano do D: '{dest_file_path_d}'")
                    copied_to_d += 1
                    file_copied_to_d_ok = True 
                except Exception as e:
                    print(f"  Błąd kopiowania do D: '{dest_file_path_d}'. {e}")
                    failed_operations.append(f"{filename} (kopia na D:)")
        except Exception as e:
            print(f"  Błąd przenoszenia z '{source_file_path}' do C: '{dest_file_path_c}'. {e}")
            failed_operations.append(f"{filename} (przeniesienie do C:)")
        
    # --- 6. Usuwanie z dodatkowego folderu źródłowego (po zakończeniu przenoszenia) ---
    removed_from_secondary = 0
    if secondary_source_exists and moved_to_c > 0:
        print(f"\nRozpoczynanie usuwania {moved_to_c} najstarszych zdjęć z '{SOURCE_PATH_SECONDARY}'...")
        
        files_in_secondary_to_consider = []
        try:
            for f in os.listdir(SOURCE_PATH_SECONDARY):
                full_path = os.path.join(SOURCE_PATH_SECONDARY, f)
                if os.path.isfile(full_path) and f.lower().endswith(IMAGE_EXTENSIONS):
                    # Zapisz parę (czas_modyfikacji, pełna_ścieżka_pliku)
                    files_in_secondary_to_consider.append((os.path.getmtime(full_path), full_path))
        except Exception as e:
            print(f"Błąd podczas listowania plików w '{SOURCE_PATH_SECONDARY}': {e}")
            # Dodaj błąd do listy, ale nie przerywaj działania
            failed_operations.append(f"Listowanie plików w {SOURCE_PATH_SECONDARY} nieudane: {e}")
            files_in_secondary_to_consider = [] # Wyzeruj listę, aby nie próbować usuwać

        if files_in_secondary_to_consider:
            # Posortuj pliki od najstarszych (najmniejszy czas modyfikacji)
            files_in_secondary_to_consider.sort() 
            
            # Określ, ile plików faktycznie usunąć (nie więcej niż liczba przeniesionych ani dostępnych)
            num_to_delete = min(moved_to_c, len(files_in_secondary_to_consider))
            
            print(f"Znaleziono {len(files_in_secondary_to_consider)} zdjęć w '{SOURCE_PATH_SECONDARY}'. Spróbuję usunąć {num_to_delete} najstarszych.")

            for i in range(num_to_delete):
                _, file_path_to_delete = files_in_secondary_to_consider[i] # Bierzemy tylko ścieżkę
                try:
                    os.remove(file_path_to_delete)
                    print(f"  -> Usunięto: '{os.path.basename(file_path_to_delete)}'")
                    removed_from_secondary += 1
                except Exception as e:
                    print(f"  Błąd usuwania '{os.path.basename(file_path_to_delete)}' z '{SOURCE_PATH_SECONDARY}'. {e}")
                    failed_operations.append(f"{os.path.basename(file_path_to_delete)} (usunięcie z {SOURCE_PATH_SECONDARY})")
        else:
            print(f"Brak zdjęć w folderze '{SOURCE_PATH_SECONDARY}' do usunięcia lub nie ma wystarczającej liczby, aby dopasować przeniesione pliki.")
    elif secondary_source_exists and moved_to_c == 0:
        print(f"Nie przeniesiono żadnych zdjęć z '{SOURCE_PATH}', więc nie usuwano z '{SOURCE_PATH_SECONDARY}'.")


    # --- Podsumowanie ---
    print("\n--- PODSUMOWANIE OPERACJI ---")
    print(f"Liczba zdjęć w folderze źródłowym na początku: {len(image_files)}")
    print(f"Liczba zdjęć przeniesionych do archiwum na C: {moved_to_c}")
    if usb_drive_present:
        print(f"Liczba zdjęć skopiowanych do archiwum na D: {copied_to_d}")
    else:
        print("Kopiowanie na D: pominięte (pendrive niedostępny).")
    print(f"Liczba zdjęć usuniętych z '{SOURCE_PATH_SECONDARY}': {removed_from_secondary}")

    if failed_operations:
        print("\nNiektóre operacje zakończyły się błędami:")
        for item in failed_operations:
            print(f"  - {item}")
    else:
        print("\nWszystkie operacje zakończyły się pomyślnie.")

    print("\nOperacja zakończona.")
    input("Naciśnij Enter, aby zakończyć...")

# Uruchomienie głównej funkcji skryptu
if __name__ == "__main__":
    main()