<?php

declare(strict_types=1);

namespace Drupal\languagewire_translation_provider\Content\HtmlPreview;

use Drupal\languagewire_translation_provider\Adapter\SystemInterface;
use Drupal\languagewire_translation_provider\Content\HtmlPreview\Result\HtmlPreviewResult;
use Psr\Log\LoggerInterface;

/**
 * HTML Preview temporary artifacts cleaner.
 */
final class HtmlPreviewTemporaryArtifactsCleaner {
  /**
   * Logger.
   */
  private LoggerInterface $logger;

  /**
   * Constructs a new HtmlPreviewTemporaryArtifactsCleaner object.
   *
   * @param \Drupal\languagewire_translation_provider\Adapter\SystemInterface $system
   *   System.
   */
  public function __construct(SystemInterface $system) {
    $this->logger = $system->logger();
  }

  /**
   * Remove preview artifacts.
   */
  public function removePreviewArtifacts(HtmlPreviewResult $previewResult): void {
    $this->removeDirectory($previewResult->getTemporaryPreviewFolderPath());
    $this->removeDirectory($previewResult->getHtmlPreviewFolderPath());
  }

  /**
   * Remove preview archives.
   *
   * @param \Drupal\languagewire_translation_provider\Content\HtmlPreview\Result\HtmlPreviewDocumentResult[] $htmlPreviews
   *   HTML previews.
   */
  public function removePreviewArchives(array $htmlPreviews): void {
    foreach ($htmlPreviews as $preview) {
      $path = $preview->getPackagePath();
      if (file_exists($path) && str_ends_with($path, ".zip")) {
        $this->deleteHtmlPreviewArchive($path);
      }
    }
  }

  /**
   * Remove directory.
   */
  private function removeDirectory(string $directoryPath): void {
    if (!is_dir($directoryPath)) {
      $this->logger->warning("Could not recursively delete \"$directoryPath\" directory, because it doesn't exist or is not a directory");
      return;
    }

    $removedSuccessfully = $this->removeDirectoryRecursively($directoryPath);
    if (!$removedSuccessfully) {
      $this->logger->warning("Could not delete all HTML Preview files in folder \"$directoryPath\"");
    }
    else {
      $this->logger->info("Deleted HTML Preview files in folder \"$directoryPath\"");
    }
  }

  /**
   * Remove directory recursively.
   */
  private function removeDirectoryRecursively(string $directoryPath): bool {
    // Iterate over all files first and then directories.
    $files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($directoryPath, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST
    );
    $deletedAll = TRUE;
    foreach ($files as $file) {
      if ($file->isDir()) {
        $deletedAll = $deletedAll && @rmdir($file->getRealPath());
      }
      else {
        $deletedAll = $deletedAll && @unlink($file->getRealPath());
      }
    }

    return $deletedAll && @rmdir($directoryPath);
  }

  /**
   * Delete HTML preview archive.
   */
  private function deleteHtmlPreviewArchive(string $path): void {
    if (!@unlink($path)) {
      $this->logger->error("Could not delete HTML Preview package located at \"$path\"");
    }
    else {
      $this->logger->info("Deleted HTML Preview package located at \"$path\"");
    }
  }

}
