<?php

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

use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Entity\Export;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Factory\DataProviderFactory;
use Exception;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\DataProvider\ExportOptionsDataProvider;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Service\Logger\ExportLoggerService;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Form\Fields\ExportOptionsFormFields;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Service\Finder\ProductsFinderService;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Service\ExportCreator\ExportCreatorService;
use WC_Product;
use WC_Product_Variation;
/**
 * Class ProductExporterService, manages the product creation process.
 *
 * @package WPDesk\Library\DropshippingExport\Service\Exporter
 */
class ProductsExporterService
{
    const MAX_PROCESS_TIME_DELAY = 5;
    const MAX_PROCESS_TIME = 120;
    const SINGLE_PRODUCT_COUNT = 1;
    /**
     * @var ExportLoggerService
     */
    private $logger;
    /**
     * @var DataProviderFactory
     */
    private $data_provider_factory;
    /**
     * @var int
     */
    private $start_time = 0;
    /**
     * @var int
     */
    private $max_execution_time = 0;
    /**
     * @var bool
     */
    private $is_finished = \false;
    /**
     *
     * @var ProductsFinderService
     */
    private $finder;
    /**
     *
     * @var ExportCreatorService
     */
    private $export_creator;
    public function __construct(DataProviderFactory $data_provider_factory, ProductsFinderService $finder, ExportCreatorService $export_creator, ExportLoggerService $logger)
    {
        $this->export_creator = $export_creator;
        $this->logger = $logger;
        $this->data_provider_factory = $data_provider_factory;
        $this->finder = $finder;
        $this->start_time = time();
        $this->max_execution_time = $this->get_max_execution_time();
    }
    public function export(Export $export_entity): Export
    {
        $products_to_export = $this->finder->find_products_to_export($export_entity, $this->get_products_in_batch($export_entity), $export_entity->get_last_position());
        if (empty($products_to_export)) {
            if ($this->stop_export($export_entity, \true)) {
                $this->export_creator->flush_export_batch($export_entity);
                return $export_entity;
            }
        }
        $last_product = null;
        foreach ($products_to_export as $product) {
            $last_product = $product;
            if ($this->is_export_should_finish()) {
                $this->export_creator->flush_export_batch($export_entity);
                return $export_entity;
            }
            if ($this->stop_export($export_entity)) {
                $this->export_creator->flush_export_batch($export_entity);
                return $export_entity;
            }
            $this->export_product($export_entity, $product);
        }
        if ($last_product !== null) {
            $this->export_creator->flush_export_batch($export_entity);
        }
        return $export_entity;
    }
    private function stop_export(Export $export_entity, bool $force = \false): bool
    {
        if (\true === $force || $export_entity->get_checked_products() >= $export_entity->get_products_count()) {
            $export_entity->set_end_date(time());
            $export_entity->set_created($export_entity->get_products_count());
            $this->is_finished = \true;
            return \true;
        }
        return \false;
    }
    public function is_finished(): bool
    {
        return $this->is_finished;
    }
    private function is_export_should_finish(): bool
    {
        $time_runing = time() - $this->start_time;
        return $this->max_execution_time <= $time_runing;
    }
    private function get_products_in_batch(Export $export_entity): int
    {
        $options_data_provider = $this->data_provider_factory->create_by_class_name(ExportOptionsDataProvider::class, ['postfix' => $export_entity->get_uid()]);
        $has_batch_option = $options_data_provider->has(ExportOptionsFormFields::PRODUCT_IN_BATCHES) && !empty($options_data_provider->get(ExportOptionsFormFields::PRODUCT_IN_BATCHES));
        $result = $has_batch_option ? $options_data_provider->get(ExportOptionsFormFields::PRODUCT_IN_BATCHES) : ExportOptionsFormFields::DEFAULT_PRODUCT_IN_BATCHES;
        return (int) $result;
    }
    private function export_product(Export $export_entity, WC_Product $product)
    {
        $export_entity->add_to_last_position(self::SINGLE_PRODUCT_COUNT);
        try {
            $this->export_creator->export($export_entity, $product);
            $export_entity->add_to_created(self::SINGLE_PRODUCT_COUNT);
            $this->logger->notice('Product: ' . $product->get_name() . ' exported');
        } catch (Exception $e) {
            $export_entity->add_to_skipped(self::SINGLE_PRODUCT_COUNT);
            $this->logger->notice($e->getMessage());
        }
    }
    private function get_max_execution_time()
    {
        $max_execution_time = intval(ini_get('max_execution_time'));
        $time = self::MAX_PROCESS_TIME - self::MAX_PROCESS_TIME_DELAY;
        if ($max_execution_time < self::MAX_PROCESS_TIME && $max_execution_time > 0) {
            $time = $max_execution_time - self::MAX_PROCESS_TIME_DELAY;
        }
        return $time;
    }
}
