И так вот мой финальный код:
import java.util.List;
import java.util.Scanner;

public class UserInterface {
private Gallery gallery;
private Catalog currentCatalog;
private Scanner scanner;


public UserInterface(Gallery gallery) {
    this.gallery = gallery;
    this.currentCatalog = gallery.getRootCatalog();
    this.scanner = new Scanner(System.in);
}

public void start() {
    boolean exit = false;
    while (!exit) {
        displayCatalogContents();
        displayMenu();
        int choice = Integer.parseInt(scanner.nextLine());
        switch (choice) {
            case 1:
                currentCatalog.removeDuplicates();
                break;
            case 2:
                createSubCatalog();
                break;
            case 3:
                moveImageFile();
                break;
            case 4:
                editMetadata();
                break;
            case 5:
                navigateBack();
                break;
            case 6:
                navigateToSubCatalog();
                break;
            case 7:
                exit = true;
                break;
            default:
                System.out.println("Неверный выбор, попробуйте снова.");
        }
    }
}

private void displayCatalogContents() {
    System.out.println("Содержимое каталога: " + currentCatalog.getPath());
    currentCatalog.displayContents();
}

private void displayMenu() {
    System.out.println("----- Что делаем? ----");
    if (!currentCatalog.getImageFiles().isEmpty()) {System.out.println("1. Удалить дубликаты в каталоге");}
    System.out.println("2. Создать подкаталог");
    if (!currentCatalog.getImageFiles().isEmpty()) {System.out.println("3. Переместить файл в другой каталог");}
    if (!currentCatalog.getImageFiles().isEmpty()) {System.out.println("4. Редактировать метаданные");}
    System.out.println("5. Вернуться назад");
    if (!currentCatalog.getSubCatalogs().isEmpty()) {System.out.println("6. Перейти в подкаталог");}
    System.out.println("7. kill");
    System.out.print("Ваш выбор: ");
}

private void createSubCatalog() {
    System.out.print("Введите название нового подкаталога: ");
    String name = scanner.nextLine();
    currentCatalog.createSubCatalog(name);
    System.out.println("Подкаталог создан и открыт.");
    currentCatalog = currentCatalog.navigateToSubCatalog(currentCatalog.getSubCatalogs().size() -1);
}

private void moveImageFile() {
    List<ImageFile> imageFiles = currentCatalog.getImageFiles();
    if (imageFiles.isEmpty()) {
        System.out.println("Нет файлов для перемещения.");
        return;
    }
    System.out.println("Файлы для перемещения:");
    for (int i = 0; i < imageFiles.size(); i++) {
        System.out.println((i + 1) + ". " + imageFiles.get(i).getName());
    }
    System.out.print("Введите номер файла для перемещения: ");
    int input = Integer.parseInt(scanner.nextLine());
    int fileIndex = input- 1;
    if (fileIndex < 0 || fileIndex >= imageFiles.size()) {
        System.out.println("Неверный номер файла.");
        return;
    }
    ImageFile mediaToMove = imageFiles.get(fileIndex);
    Catalog targetCatalog = selectCatalog();
    if (targetCatalog != null) {
        currentCatalog.moveImageFile(mediaToMove, targetCatalog);
    }
}

private Catalog selectCatalog() {
    Catalog catalog = gallery.getRootCatalog();
    while (true) {
        System.out.println("Текущий каталог: " + catalog.getPath());
        List<Catalog> subCatalogs = catalog.getSubCatalogs();
        System.out.println("Подкаталоги:");
        for (int i = 0; i < subCatalogs.size(); i++) {
            System.out.println((i + 1) + ". " + subCatalogs.get(i).getName());
        }
        System.out.println("0. Выбрать текущий каталог");
        System.out.print("Введите номер подкаталога для перехода или 0 для выбора текущего каталога: ");
        int choice = Integer.parseInt(scanner.nextLine());
        if (choice == 0) {
            return catalog;
        } else if (choice > 0 && choice <= subCatalogs.size()) {
            catalog = subCatalogs.get(choice - 1);
        } else {
            System.out.println("Неверный выбор, попробуйте снова.");
        }
    }
}


private void editMetadata() {
    List<ImageFile> mediaFiles = currentCatalog.getImageFiles();
    if (mediaFiles.isEmpty()) {
        System.out.println("Нет файлов для редактирования.");
        return;
    }
    System.out.println("Файлы для редактирования метаданных:");
    for (int i = 0; i < mediaFiles.size(); i++) {
        System.out.println((i + 1) + ". " + mediaFiles.get(i).getName());
    }
    System.out.print("Введите номер файла для редактирования метаданных: ");
    int fileIndex = Integer.parseInt(scanner.nextLine()) - 1;
    if (fileIndex < 0 || fileIndex >= mediaFiles.size()) {
        System.out.println("Неверный номер файла.");
        return;
    }
    ImageFile mediaFile = mediaFiles.get(fileIndex);
    Metadata metadata = mediaFile.getMetadata();
    boolean editing = true;
    while (editing) {
        System.out.println("Текущие метаданные файла " + mediaFile.getName() + ":");
        System.out.println("1. Автор: " + metadata.getAuthor());
        System.out.println("2. Дата съёмки: " + metadata.getDateTaken());
        System.out.println("3. Описание: " + metadata.getDescription());
        System.out.println("4. Завершить редактирование");
        System.out.print("Введите номер поля для редактирования: ");
        int choice = Integer.parseInt(scanner.nextLine());

        switch (choice) {
            case 1:
                System.out.print("Введите новое значение для 'Автор': ");
                String newAuthor = scanner.nextLine();
                metadata.edit("author", newAuthor);
                System.out.println("Автор обновлён.");
                break;
            case 2:
                System.out.print("Введите новую дату (в формате yyyy-MM-dd): ");
                String newDate = scanner.nextLine();
                metadata.edit("date", newDate);
                System.out.println("Дата съёмки обновлена.");
                break;
            case 3:
                System.out.print("Введите новое описание: ");
                String newDescription = scanner.nextLine();
                metadata.edit("description", newDescription);
                System.out.println("Описание обновлено.");
                break;
            case 4:
                editing = false;
                break;
            default:
                System.out.println("Неверный выбор, попробуйте снова.");
        }
    }
    mediaFile.editMetadata(metadata);
}

private void navigateBack() {
    if (currentCatalog.getParentCatalog() != null) {
        currentCatalog = currentCatalog.getParentCatalog();
    } else {
        System.out.println("Вы находитесь в корневом каталоге.");
    }
}

private void navigateToSubCatalog() {
    System.out.print("Введите номер подкатолога: ");
    currentCatalog.displaySubCatalogs();
    int index = Integer.parseInt(scanner.nextLine()) - 1;
    Catalog subCatalog = currentCatalog.navigateToSubCatalog(index);
    if (subCatalog != null) {
        currentCatalog = subCatalog;
    } else {
        System.out.println("Подкаталог не найден.");
    }
}
}

import java.io.IOException;

public class PhotoGallery {
public static void main(String[] args) {
String rootPath = "E:\святой хентай"; // Укажите путь к вашей галерее


    // Инициализация галереи
    Gallery gallery = new Gallery(rootPath);
    try {
        gallery.loadGallery();
    } catch (IOException e) {
        System.out.println("Ошибка при загрузке галереи: " + e.getMessage());
        return;
    }

    // Запуск пользовательского интерфейса
    UserInterface ui = new UserInterface(gallery);
    ui.start();
}
}

import java.io.File;
import java.util.Date;

public class Metadata {
private String author;
private Date dateTaken;
private String description;


public Metadata(File file) {
    this.author = "";
    this.dateTaken = new Date(file.lastModified());
    this.description = "";

    //TODO позыркать можно ли доставать трушные метаданные
}

public void edit(String field, String newValue) {
    switch (field.toLowerCase()) {
        case "author":
            this.author = newValue;
            break;
        case "date":
            break;
        case "description":
            this.description = newValue;
            break;
        default:
            System.out.println("Неизвестное поле метаданных.");
    }
}

public String getAuthor() {
    return author;
}

public Date getDateTaken() {
    return dateTaken;
}

public String getDescription() {
    return description;
}
}

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Arrays;

public class ImageFile {
private String name;
private String path;
private Metadata metadata;


public ImageFile(File file) {
    this.name = file.getName();
    this.path = file.getAbsolutePath();
    this.metadata = new Metadata(file);
}

public boolean isDuplicateOf(ImageFile otherFile) {
    try {
        byte[] thisFileBytes = Files.readAllBytes(new File(this.path).toPath());
        byte[] otherFileBytes = Files.readAllBytes(new File(otherFile.getPath()).toPath());
        return Arrays.equals(thisFileBytes, otherFileBytes);
    } catch (IOException e) {
        System.out.println("Ошибка при сравнении файлов: " + e.getMessage());
        return false;
    }
}

public void editMetadata(Metadata newMetadata) {
    this.metadata = newMetadata;
    // Здесь можно добавить код для сохранения метаданных в файл
    System.out.println("Метаданные файла " + name + " обновлены.");
}

public void delete() {
    File file = new File(path);
    if (file.delete()) {
        System.out.println("Файл " + name + " удалён.");
    } else {
        System.out.println("Не удалось удалить файл " + name + ".");
    }
}

public String getName() {
    return name;
}

public String getPath() {
    return path;
}

public Metadata getMetadata() {
    return metadata;
}
}

import java.io.File;
import java.io.IOException;

public class Gallery {
private String rootPath;
private Catalog rootCatalog;


public Gallery(String rootPath) {
    this.rootPath = rootPath;
    this.rootCatalog = new Catalog(new File(rootPath), null);
}

public void loadGallery() throws IOException {
    rootCatalog.loadContents();
}

public Catalog getRootCatalog() {
    return rootCatalog;
}
}

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class Catalog {
private String name;
private String path;
private Catalog parentCatalog;
private List subCatalogs;
private List imageFiles;


public Catalog(File dir, Catalog parentCatalog) {
    this.name = dir.getName();
    this.path = dir.getAbsolutePath();
    this.parentCatalog = parentCatalog;
    this.subCatalogs = new ArrayList<>();
    this.imageFiles = new ArrayList<>();
}

public void loadContents() throws IOException {
    File dir = new File(path);
    File[] files = dir.listFiles();
    if (files == null) {
        throw new IOException("Не удалось получить содержимое каталога: " + path);
    }
    for (File file : files) {
        if (file.isDirectory()) {
            Catalog subCatalog = new Catalog(file, this);
            subCatalog.loadContents();
            subCatalogs.add(subCatalog);
        } else if (isImageFile(file)) {
            ImageFile imageFile = new ImageFile(file);
            imageFiles.add(imageFile);
        }
    }
}

private boolean isImageFile(File file) {
    String[] imageExtensions = { ".jpg", ".jpeg", ".png", ".gif", ".bmp" };
    String fileName = file.getName().toLowerCase();
    for (String ext : imageExtensions) {
        if (fileName.endsWith(ext))
            return true;
    }
    return false;
}

public void displayContents() {
    System.out.println("Каталог: " + path);
    System.out.println("Подкаталоги:");
    for (int i = 0; i < subCatalogs.size(); i++) {
        System.out.println((i + 1) + ". " + subCatalogs.get(i).getName());
    }
    System.out.println("Файлы изображений:");
    for (int i = 0; i < imageFiles.size(); i++) {
        System.out.println((i + 1) + ". " + imageFiles.get(i).getName());
    }
}

public void displayImages() {
    System.out.println("Файлы изображений:");
    for (int i = 0; i < imageFiles.size(); i++) {
        System.out.println((i + 1) + ". " + imageFiles.get(i).getName());
    }
}

public void displaySubCatalogs() {
    System.out.println("Подкаталоги:");
    for (int i = 0; i < subCatalogs.size(); i++) {
        System.out.println((i + 1) + ". " + subCatalogs.get(i).getName());
    }
}

public void removeDuplicates() {
    System.out.println("Поиск и удаление дубликатов...");
    List<ImageFile> duplicates = new ArrayList<>();
    for (int i = 0; i < imageFiles.size(); i++) {
        ImageFile img1 = imageFiles.get(i);
        for (int j = i + 1; j < imageFiles.size(); j++) {
            ImageFile img2 = imageFiles.get(j);
            if (img1.isDuplicateOf(img2)) {
                duplicates.add(img2);
            }
        }
    }
    int temp = 0;
    for (ImageFile duplicate : duplicates) {
        duplicate.delete();
        imageFiles.remove(duplicate);
        System.out.println("Удалён дубликат: " + duplicate.getName());
        temp ++;
    }
    System.out.println(temp == 0 ? "Дубликаты не найдены." : "Удалено " + temp + " дубликатов.");
}

public Catalog createSubCatalog(String name) {
    File newDir = new File(path + File.separator + name);
    if (newDir.mkdir()) {
        Catalog newCatalog = new Catalog(newDir, this);
        subCatalogs.add(newCatalog);
        return newCatalog;
    } else {
        System.out.println("Не удалось создать подкаталог.");
        return null;
    }
}

public void addImageFile(ImageFile imageFile) {
    imageFiles.add(imageFile);
}

public void moveImageFile(ImageFile file, Catalog targetCatalog) {
    File sourceFile = new File(file.getPath());
    File targetFile = new File(targetCatalog.getPath() + File.separator + file.getName());
    if (sourceFile.renameTo(targetFile)) {
        imageFiles.remove(file);
        targetCatalog.addImageFile(new ImageFile(targetFile));
        System.out.println("Файл " + file.getName() + " перемещён в " + targetCatalog.getPath());
    } else {
        System.out.println("Не удалось переместить файл.");
    }
}

public String getName() {
    return name;
}

public String getPath() {
    return path;
}

public Catalog getParentCatalog() {
    return parentCatalog;
}

public List<Catalog> getSubCatalogs() {
    return subCatalogs;
}

public List<ImageFile> getImageFiles() {
    return imageFiles;
}

    public Catalog navigateToSubCatalog(int index) {
    if (index < subCatalogs.size()) {
        return subCatalogs.get(index);
    } return null;
}
// public Catalog navigateToSubCatalog(String name) {
// for (Catalog subCatalog : subCatalogs) {
// if (subCatalog.getName().equalsIgnoreCase(name)) {
// return subCatalog;
// }
// }
// return null; //Чисто теоретически мы в жопе если это произойдет.
// }
}


напиши к нему документацию