<?php

namespace DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Service\Locator;

use DropshippingExportFreeVendor\WPDesk\Forms\Field\CheckboxField;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Infrastructure\Config\Config;
use RuntimeException;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Infrastructure\Data\DataFormat;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\File\FileObject;
use Exception;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Factory\DataProviderFactory;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Form\Fields\ExportOptionsFormFields;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\DataProvider\ExportOptionsDataProvider;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Service\Archive\ArchvieService;
class FileLocatorService
{
    private Config $config;
    private DataProviderFactory $data_provider_factory;
    public function __construct(Config $config, DataProviderFactory $data_provider_factory)
    {
        $this->config = $config;
        $this->data_provider_factory = $data_provider_factory;
    }
    public function get_file_path_to_export(string $uid, string $extension): string
    {
        $file_path = $this->get_file_path($uid, $extension);
        $root = $this->config->get_param('assets.root')->getAsString();
        $file_path = $this->get_root_path($file_path);
        $this->create_directory_path_if_not_exists($file_path);
        if (!$this->is_path_secure($root, $file_path)) {
            throw new RuntimeException('Directory traversal security error');
        }
        return $file_path;
    }
    public function generate_zip_path(string $file_location): string
    {
        if (strpos($file_location, ArchvieService::ZIP_EXTENSION) !== \false) {
            return $file_location;
        } else {
            return $file_location . ArchvieService::ZIP_EXTENSION;
        }
    }
    public function get_url_to_file(string $uid, bool $check_if_file_exists = \true): string
    {
        $file_path = $this->get_file_path_by_uid($uid);
        if ($check_if_file_exists === \false || $this->check_if_file_exists($this->get_root_path($file_path))) {
            $site_url = $this->config->get_param('assets.root_url')->getAsString();
            $file_path = $site_url . str_replace('%2F', '/', rawurlencode($file_path));
        } else {
            $file_path = '';
        }
        return $file_path;
    }
    public function get_url_to_zip_file(string $uid, bool $check_if_file_exists = \true): string
    {
        if (!$this->has_zip_file($uid)) {
            return '';
        }
        $file_path = $this->get_file_path_by_uid($uid);
        $file_path = $this->generate_zip_path($file_path);
        if ($check_if_file_exists === \false || $this->check_if_file_exists($this->get_root_path($file_path))) {
            $site_url = $this->config->get_param('assets.root_url')->getAsString();
            $file_path = $site_url . str_replace('%2F', '/', rawurlencode($file_path));
        } else {
            $file_path = '';
        }
        return $file_path;
    }
    public function get_file_path(string $uid, string $extension): string
    {
        $file_path = $this->get_file_path_by_uid($uid);
        if (empty($file_path)) {
            $file_path = $this->generate_tmp_file_path($uid, $extension, \true);
        }
        return $file_path;
    }
    public function get_source_file(string $uid): FileObject
    {
        $tmp_dir = $this->get_tmp_dir($uid);
        $file_location = $tmp_dir . $uid;
        if (!$this->is_path_secure($tmp_dir, $file_location)) {
            throw new RuntimeException('Directory traversal security error');
        }
        return new FileObject($file_location);
    }
    public function get_converted_file(string $uid): FileObject
    {
        $tmp_dir = $this->get_tmp_dir($uid);
        $file_location = $tmp_dir . $uid . '.' . DataFormat::XML;
        if (!$this->is_path_secure($tmp_dir, $file_location)) {
            throw new RuntimeException('Directory traversal security error');
        }
        return new FileObject($file_location);
    }
    public function is_source_file_exists(string $uid): bool
    {
        try {
            $this->get_source_file($uid);
            return \true;
        } catch (Exception $e) {
            return \false;
        }
    }
    public function is_converted_file_exists(string $uid): bool
    {
        try {
            $this->get_converted_file($uid);
            return \true;
        } catch (Exception $e) {
            return \false;
        }
    }
    public function create_directory_path_if_not_exists(string $file_path)
    {
        if (!file_exists(dirname($file_path))) {
            \wp_mkdir_p(dirname($file_path));
        }
    }
    public function is_path_secure(string $expected_dir_location, string $file_path): bool
    {
        $base = realpath($expected_dir_location);
        $user_path = realpath(dirname($file_path));
        return !($user_path === \false || strpos($user_path, $base) !== 0);
    }
    public function get_tmp_dir(string $uid): string
    {
        return trailingslashit($this->config->get_param('files.tmp.dir')->get() . $uid);
    }
    public function generate_tmp_file_path(string $uid, string $extension = '', $is_relative = \false): string
    {
        $tmp_file = $this->get_tmp_dir($uid) . $uid;
        if (!empty($extension)) {
            $tmp_file .= '.' . $extension;
        }
        if ($is_relative) {
            $root = $this->config->get_param('assets.root')->getAsString();
            $tmp_file = \str_replace($root, '/', $tmp_file);
        }
        return $tmp_file;
    }
    public function check_if_dir_exists(string $save_location): bool
    {
        $pathinfo = pathinfo($save_location);
        return file_exists($pathinfo['dirname']);
    }
    public function check_if_file_is_dir(string $save_location): bool
    {
        return is_dir($save_location);
    }
    public function check_if_file_exists(string $location): bool
    {
        return \false !== realpath($location);
    }
    private function get_file_path_by_uid(string $uid): string
    {
        $file_path = '';
        $options_data_provider = $this->data_provider_factory->create_by_class_name(ExportOptionsDataProvider::class, ['postfix' => $uid]);
        if ($options_data_provider->has(ExportOptionsFormFields::FILE_FTP_PATH)) {
            $file_path = $options_data_provider->get(ExportOptionsFormFields::FILE_FTP_PATH);
            return $file_path;
        }
        return $file_path;
    }
    private function has_zip_file(string $uid): bool
    {
        $options_data_provider = $this->data_provider_factory->create_by_class_name(ExportOptionsDataProvider::class, ['postfix' => $uid]);
        if ($options_data_provider->has(ExportOptionsFormFields::SAVE_IMAGES_AS_ZIP)) {
            return $options_data_provider->get(ExportOptionsFormFields::SAVE_IMAGES_AS_ZIP) === CheckboxField::VALUE_TRUE;
        }
        return \false;
    }
    private function get_root_path(string $relative_path): string
    {
        $root = $this->config->get_param('assets.root')->getAsString();
        $relative_path = str_replace('//', '/', $root . $relative_path);
        return $relative_path;
    }
}
