<?php
declare(strict_types=1);

namespace App\Framework\Filesystem;

/**
 * Repräsentiert ein Verzeichnis im Dateisystem mit Lazy-Loading-Unterstützung.
 *
 * @property-read string $path Pfad zum Verzeichnis
 * @property-read Storage $storage Storage-Implementierung
 * @property-read array $contents Verzeichnisinhalt (lazy geladen)
 */
final readonly class Directory
{
    public function __construct(
        public string $path,
        public Storage $storage,
        public array $contents = []
    ) {}

    /**
     * Prüft, ob das Verzeichnis existiert
     */
    public function exists(): bool
    {
        return is_dir($this->path);
    }

    /**
     * Erstellt das Verzeichnis, falls es nicht existiert
     */
    public function create(int $permissions = 0755, bool $recursive = true): void
    {
        $this->storage->createDirectory($this->path, $permissions, $recursive);
    }

    /**
     * Gibt alle Dateien im Verzeichnis zurück
     *
     * @return File[] Liste von Dateiobjekten
     */
    public function getFiles(): array
    {
        $paths = $this->storage->listDirectory($this->path);
        $files = [];

        foreach ($paths as $path) {
            if (is_file($path)) {
                $files[] = FilesystemFactory::createFile($path, $this->storage);
            }
        }

        return $files;
    }

    /**
     * Gibt alle Unterverzeichnisse zurück
     *
     * @return Directory[] Liste von Verzeichnisobjekten
     */
    public function getDirectories(): array
    {
        $paths = $this->storage->listDirectory($this->path);
        $directories = [];

        foreach ($paths as $path) {
            if (is_dir($path)) {
                $directories[] = FilesystemFactory::createDirectory($path, $this->storage);
            }
        }

        return $directories;
    }

    /**
     * Gibt alle Dateien und Unterverzeichnisse in einem Durchgang zurück
     *
     * @return array{files: File[], directories: Directory[]}
     */
    public function getContents(): array
    {
        $paths = $this->storage->listDirectory($this->path);
        $files = [];
        $directories = [];

        foreach ($paths as $path) {
            if (is_file($path)) {
                $files[] = FilesystemFactory::createFile($path, $this->storage);
            } elseif (is_dir($path)) {
                $directories[] = FilesystemFactory::createDirectory($path, $this->storage);
            }
        }

        return ['files' => $files, 'directories' => $directories];
    }

    /**
     * Gibt eine Datei im Verzeichnis zurück
     */
    public function getFile(string $filename): File
    {
        $path = $this->path . DIRECTORY_SEPARATOR . $filename;
        return FilesystemFactory::createFile($path, $this->storage);
    }

    /**
     * Gibt ein Unterverzeichnis zurück
     */
    public function getDirectory(string $name): Directory
    {
        $path = $this->path . DIRECTORY_SEPARATOR . $name;
        return FilesystemFactory::createDirectory($path, $this->storage);
    }

    /**
     * Lädt den Verzeichnisinhalt neu
     */
    public function refresh(): Directory
    {
        return FilesystemFactory::createDirectory($this->path, $this->storage);
    }
}
