<?php

declare(strict_types=1);

namespace Flowaxy\Support\Helpers;

use Flowaxy\Infrastructure\Filesystem\Archive\Zip;
use Exception;
use ZipArchive;

use function basename;
use function is_array;

// Хелпер для роботи з архівами
// Обгортка над Archive класами
final class ArchiveHelper
{
    // Розпакувати архів
    public static function extract(string $archivePath, string $destinationPath): bool
    {
        if (!FileHelper::exists($archivePath)) {
            return false;
        }

        $zip = new Zip($archivePath);
        $result = $zip->extractTo($destinationPath);
        $zip->close();

        return $result;
    }

    // Створити архів
    public static function compress(string|array $paths, string $archivePath): bool
    {
        $zip = new Zip($archivePath, ZipArchive::CREATE | ZipArchive::OVERWRITE);

        $paths = is_array($paths) ? $paths : [$paths];

        foreach ($paths as $path) {
            if (FileHelper::isFile($path)) {
                $zip->addFile($path, basename($path));
            } elseif (FileHelper::isDirectory($path)) {
                $zip->addDirectory($path);
            }
        }

        $result = $zip->close();

        return $result;
    }

    // Додати файл до архіву
    public static function addFile(string $archivePath, string $filePath, ?string $localName = null): bool
    {
        $zip = new Zip($archivePath);
        $result = $zip->addFile($filePath, $localName);
        $zip->close();

        return $result;
    }

    // Додати директорію до архіву
    public static function addDirectory(string $archivePath, string $directoryPath): bool
    {
        $zip = new Zip($archivePath);
        $result = $zip->addDirectory($directoryPath);
        $zip->close();

        return $result;
    }

    // Отримати список файлів в архіві
    public static function listFiles(string $archivePath): array|false
    {
        if (!FileHelper::exists($archivePath)) {
            return false;
        }

        $zip = new Zip($archivePath, ZipArchive::RDONLY);
        $files = $zip->listFiles();
        $zip->close();

        return $files;
    }

    // Отримати файл з архіву
    public static function getFile(string $archivePath, string $fileName): string|false
    {
        if (!FileHelper::exists($archivePath)) {
            return false;
        }

        $zip = new Zip($archivePath, ZipArchive::RDONLY);
        $content = $zip->getFromName($fileName);
        $zip->close();

        return $content;
    }

    // Видалити файл з архіву
    public static function deleteFile(string $archivePath, string $fileName): bool
    {
        if (!FileHelper::exists($archivePath)) {
            return false;
        }

        $zip = new Zip($archivePath);
        $result = $zip->deleteName($fileName);
        $zip->close();

        return $result;
    }

    // Перевірити, чи архів валідний
    public static function isValid(string $archivePath): bool
    {
        if (!FileHelper::exists($archivePath)) {
            return false;
        }

        try {
            $zip = new Zip($archivePath, ZipArchive::RDONLY);
            $isValid = $zip->isOpen();
            $zip->close();

            return $isValid;
        } catch (\Exception $e) {
            return false;
        }
    }

    // Отримати розмір архіву
    public static function getSize(string $archivePath): int|false
    {
        return FileHelper::size($archivePath);
    }

    // Отримати кількість файлів в архіві
    public static function getCount(string $archivePath): int|false
    {
        if (!FileHelper::exists($archivePath)) {
            return false;
        }

        $zip = new Zip($archivePath, ZipArchive::RDONLY);
        $count = $zip->getEntryCount();
        $zip->close();

        return $count;
    }
}
