<?php

declare(strict_types=1);

namespace Drupal\sobki_assets\Service;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\sobki_assets\Form\AssetsUploadForm;

/**
 * A helper service to extract the uploaded archive.
 */
class ArchiveExtractor implements ArchiveExtractorInterface {

  /**
   * Constructor.
   */
  public function __construct(
    protected EntityTypeManagerInterface $entityTypeManager,
  ) {}

  /**
   * {@inheritdoc}
   */
  public function extract(string $archive_path, string $destination, callable $success, callable $fail): void {
    $zip = new \ZipArchive();
    if ($zip->open($archive_path) === TRUE) {
      $zip->extractTo($destination);
      $filenames = $this->getExtractedArchiveFilenames($zip);
      $zip->close();
      $this->createManagedFiles($filenames);
      $success($filenames);
    }
    else {
      $fail();
    }
  }

  /**
   * Create managed files from filenames within destination directory.
   *
   * @param string[] $filenames
   *   The filenames.
   */
  protected function createManagedFiles(array $filenames): void {
    $fileStorage = $this->entityTypeManager->getStorage('file');
    foreach ($filenames as $filename) {
      /** @var \Drupal\file\FileInterface $file */
      $file = $fileStorage->create([
        'uri' => AssetsUploadForm::DESTINATION_DIRECTORY . '/' . $filename,
      ]);
      $file->setPermanent();
      $file->save();
    }
  }

  /**
   * Get the extracted filenames of the archive.
   *
   * @param \ZipArchive $archive
   *   The archive zip file.
   *
   * @return string[]
   *   Extracted filenames.
   */
  protected function getExtractedArchiveFilenames(\ZipArchive $archive): array {
    $extractedFiles = [];
    for ($i = 0; $i < $archive->numFiles; ++$i) {
      $name = $archive->getNameIndex($i);
      if ($name) {
        $extractedFiles[] = $name;
      }
    }

    return $extractedFiles;
  }

}
