<?php

declare(strict_types=1);

namespace App\Application\Media;

use App\Domain\Media\ImageProcessor;
use App\Domain\Media\ImageRepository;
use App\Domain\Media\ImageVariantRepository;
use FilesystemIterator;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;

final readonly class MediaCleanupService
{
    public function __construct(
        private ImageRepository $imageRepository,
        private ImageProcessor $imageProcessor,
        private ImageVariantRepository $imageVariantRepository,
    ) {
    }

    /**
     * Cleanup Media Files that are not saved to Database
     */
    public function cleanupUnusedFiles(string $path = '/var/www/html/storage/uploads/2025'): array
    {
        $deletedFiles = [];

        $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS));

        /** @var \SplFileInfo $file */
        foreach ($rii as $file) {
            $variant = $this->imageVariantRepository->findByFilename($file->getFilename());

            if ($variant === null) {
                $image = $this->imageRepository->findByFilename($file->getFilename());
                if ($image === null) {
                    $success = unlink($file->getPathname());
                    if ($success) {
                        $deletedFiles[] = $file->getPathname();
                    }
                }
            }
        }

        return $deletedFiles;
    }

    /**
     * Delete empty folders
     */
    public function cleanupEmptyDirectories(string $path = '/var/www/html/storage/uploads/2025'): array
    {
        $emptyDirs = [];

        $iterator = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),
            RecursiveIteratorIterator::CHILD_FIRST // Ordner erst nach dem Inhalt prüfen
        );

        foreach ($iterator as $fileInfo) {
            if ($fileInfo->isDir()) {
                // Verzeichnis öffnen und prüfen, ob es leer ist
                $files = array_diff(scandir($fileInfo->getPathname()), ['.', '..']);
                if (empty($files)) {
                    $success = rmdir($fileInfo->getPathname());
                    if ($success) {
                        $emptyDirs[] = $fileInfo->getPathname();
                    }
                }
            }
        }

        return $emptyDirs;
    }

    /**
     * Create image variants for all images
     */
    public function createImageVariants(): array
    {
        $createdVariants = [];
        $images = $this->imageRepository->findAll();

        foreach ($images as $image) {
            $variants = $this->imageProcessor->createAllVariants($image);

            foreach ($variants as $variant) {
                try {
                    $this->imageVariantRepository->save($variant);
                    $createdVariants[] = $variant;
                } catch (\Throwable $th) {
                    // Variant already saved, skip
                }
            }
        }

        return $createdVariants;
    }

    /**
     * Full cleanup - files, directories and variant creation
     */
    public function fullCleanup(string $path = '/var/www/html/storage/uploads/2025'): array
    {
        return [
            'deleted_files' => $this->cleanupUnusedFiles($path),
            'deleted_directories' => $this->cleanupEmptyDirectories($path),
            'created_variants' => $this->createImageVariants(),
        ];
    }
}
