<?php

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

use WC_Product;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Factory\ProductsFactory;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Factory\DataProviderFactory;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Entity\Export;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\ProductFields\Collection\ProductFieldCollection;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\DataProvider\ExportOptionsDataProvider;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Service\Locator\FileLocatorService;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Form\Fields\ExportOptionsFormFields;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\DataProvider\ExportFileTypeDataProvider;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Form\Fields\ExportFileTypeFormFields;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Factory\WriterFactory;
use DropshippingExportFreeVendor\WPDesk\Forms\Field\CheckboxField;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Factory\PriceCompareFactory;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Service\Archive\ArchvieService;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\PriceCompare\PriceCompareConfig;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Service\Writer\ColumnDelimeter;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\ProductFields\ProductFieldImgLocationValue;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Service\Writer\ExternalData;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Service\Writer\XML\GmcXmlWriter;
use Exception;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Service\Writer\FileLocker;
use DropshippingExportFreeVendor\WPDesk\Library\DropshippingExport\Service\Writer\Generator;
class ExportCreatorService
{
    public const FIRST_POSITION = 1;
    private DataProviderFactory $data_provider_factory;
    private ProductsFactory $products_factory;
    private FileLocatorService $file_locator;
    private WriterFactory $writer_factory;
    private ArchvieService $archive_service;
    private PriceCompareFactory $price_compare_factory;
    /**
     * 
     * @var Generator[]
     */
    private array $writers = [];
    private ?bool $is_new_export = null;
    public function __construct(ProductsFactory $products_factory, DataProviderFactory $data_provider_factory, WriterFactory $writer_factory, FileLocatorService $file_locator, ArchvieService $archive_service, PriceCompareFactory $price_compare_factory)
    {
        $this->products_factory = $products_factory;
        $this->data_provider_factory = $data_provider_factory;
        $this->file_locator = $file_locator;
        $this->writer_factory = $writer_factory;
        $this->archive_service = $archive_service;
        $this->price_compare_factory = $price_compare_factory;
    }
    public function export(Export $export, WC_Product $product): Export
    {
        $config = $this->get_price_compare_config($export->get_uid());
        $file_path = $this->file_locator->get_file_path_to_export($export->get_uid(), $config->get_supported_extension());
        if ($this->is_new_export === null) {
            $this->is_new_export = $export->get_last_position() === 1 || !$this->file_locator->check_if_file_exists($file_path);
        }
        $product_fields_collection = $this->products_factory->create_product_field_collection($export->get_uid(), $config, $product);
        $writer = $this->get_writer($config->get_writer_class_name());
        if ($writer instanceof ColumnDelimeter) {
            $writer->set_delimeter($this->get_separator($export));
        }
        if ($writer instanceof ExternalData) {
            $title = $this->get_export_title($export);
            $writer->set_data([GmcXmlWriter::TAG_TITLE => $title, GmcXmlWriter::TAG_LINK => $this->file_locator->get_url_to_file($export->get_uid(), \false), GmcXmlWriter::TAG_DESCRIPTION => $title]);
        }
        try {
            $writer->add_to_batch($product_fields_collection);
        } catch (Exception $e) {
            throw $e;
        }
        if ($this->should_create_zip_file($export)) {
            $is_new_export = $export->get_last_position() === 1;
            $this->archive_service->set_export_as_new($is_new_export);
            $this->archive_service->compress_files($this->file_locator->generate_zip_path($file_path), $this->get_images_paths_to_archive($product_fields_collection));
        }
        return $export;
    }
    public function flush_export_batch(Export $export): void
    {
        $config = $this->get_price_compare_config($export->get_uid());
        $writer = $this->get_writer($config->get_writer_class_name());
        if (\is_null($writer) || !$writer->has_batch() && $export->get_last_position() > 0) {
            return;
        }
        $file_path = $this->file_locator->get_file_path_to_export($export->get_uid(), $config->get_supported_extension());
        $file_locker = new FileLocker($writer);
        $file_locker->flush($file_path, $this->is_new_export ?? \true);
    }
    private function get_writer(string $class_name): Generator
    {
        if (isset($this->writers[$class_name])) {
            return $this->writers[$class_name];
        }
        $this->writers[$class_name] = $this->writer_factory->create_writer_by_class_name($class_name);
        return $this->writers[$class_name];
    }
    private function get_price_compare_config(string $uid): PriceCompareConfig
    {
        $type_provider = $this->data_provider_factory->create_by_class_name(ExportFileTypeDataProvider::class, ['postfix' => $uid]);
        $type = $type_provider->get(ExportFileTypeFormFields::EXPORT_TYPE);
        return $this->price_compare_factory->get_config_by_id($type);
    }
    private function get_images_paths_to_archive(ProductFieldCollection $collection): array
    {
        $rows = [];
        foreach ($collection as $product_field) {
            if ($product_field instanceof ProductFieldImgLocationValue) {
                return $product_field->get_file_locations() ?? [];
            }
        }
        return $rows;
    }
    private function get_separator(Export $export): string
    {
        $options = $this->data_provider_factory->create_by_class_name(ExportOptionsDataProvider::class, ['postfix' => $export->get_uid()]);
        return $options->get(ExportOptionsFormFields::PRODUCT_COLUMN_SEPARATOR);
    }
    private function get_export_title(Export $export): string
    {
        $options = $this->data_provider_factory->create_by_class_name(ExportOptionsDataProvider::class, ['postfix' => $export->get_uid()]);
        return $options->get(ExportOptionsFormFields::EXPORT_NAME);
    }
    private function should_create_zip_file(Export $export): bool
    {
        $options_dp = $this->data_provider_factory->create_by_class_name(ExportOptionsDataProvider::class, ['postfix' => $export->get_uid()]);
        return $options_dp->has(ExportOptionsFormFields::SAVE_IMAGES_AS_ZIP) && $options_dp->get(ExportOptionsFormFields::SAVE_IMAGES_AS_ZIP) === CheckboxField::VALUE_TRUE;
    }
}
