<?php

use PhpZip\Constants\ZipCompressionMethod;
use PhpZip\ZipFile;

class Backpack_Compress
{
    /**
     * Constructor method for initializing the Backpack instance.
     *
     * @param Backpack $backpack An instance of the Backpack class.
     *
     * @return void
     */
    public function __construct(private Backpack $backpack)
    {
        //
    }

    /**
     * Creates a ZIP archive and compresses files or directories into it. Allows specifying files or directories to ignore during compression.
     *
     * @param string       $filename The full path of the output ZIP file to be created.
     * @param string|array $path     The path(s) to the files or directories to be added to the ZIP archive. Can be a single string or an array of strings.
     * @param string|array $ignore   Optional. Path(s) to files or directories to be ignored during compression. Can be a single string or an array of strings.
     *
     * @return string|false Returns the filename of the created ZIP file if successful, or false if an error occurs.
     */
    public function zip(string $filename, string|array $path, string|array $ignore = [])
    {
        $zip = new ZipFile();

        if (is_string($path) && str_contains($path, ",")) {
            $path = explode(",", $path);
        }

        if (is_string($ignore) && str_contains($ignore, ",")) {
            $ignore = explode(",", $ignore);
        }

        ray($path);

        try {
            if (is_string($path)) {
                $this->backpack->log("Path provided as string: " . $path);
                $path = [$path];
            }

            if (is_string($ignore) && ! empty($ignore)) {
                $this->backpack->log("Ignores provided as string: " . $ignore);
                $ignore = [$ignore];
            } else {
                $this->backpack->log("No ignores provided, using empty array");
                $ignore = [];
            }

            $documentRoot  = $_SERVER['DOCUMENT_ROOT'];
            $removablePath = realpath($documentRoot . DIRECTORY_SEPARATOR . ".." . DIRECTORY_SEPARATOR);

            foreach ($path as $file) {
                $localPath = str_replace($removablePath, "", $file);

                if (is_dir($file)) {
                    $this->backpack->log("Compressing directory: " . $file);
                    $directoryIterator = new \RecursiveDirectoryIterator($file);
                    $ignoreIterator = new \PhpZip\Util\Iterator\IgnoreFilesRecursiveFilterIterator(
                        $directoryIterator,
                        $ignore
                    );
                    $zip->addFilesFromIterator($ignoreIterator, $localPath, ZipCompressionMethod::DEFLATED);
                } elseif (is_file($file)) {
                    $this->backpack->log("Compressing file: " . $file);
                    $zip->addFile($file, null, ZipCompressionMethod::DEFLATED);
                } else {
                    $this->backpack->log("Failed to compress file. File not found: " . $file);
                }
            }

            $zip->saveAsFile($filename);
        } catch (\PhpZip\Exception\ZipException $e) {
            $this->backpack->log("Failed to compress file. Exception: " . $e->getMessage());
            return false;
        } finally {
            $zip->close();
        }

        return $filename;
    }
}
