<?php

namespace Firebear\ImportExport\Test\Integration;

use Firebear\ImportExport\Api\Export\History\GetByIdInterface;
use Firebear\ImportExport\Api\JobRepositoryInterface;
use Firebear\ImportExport\Model\ExportJob\Processor;
use Firebear\ImportExport\Helper\Data;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Filesystem;
use Magento\Framework\ObjectManagerInterface;
use Magento\TestFramework\Helper\Bootstrap;
use Firebear\ImportExport\Model\ResourceModel\Export\History as ExportHistory;
use Exception;

class AbstractExport extends \PHPUnit\Framework\TestCase
{
    /**
     * @var ObjectManagerInterface
     */
    protected $objectManager;

    /**
     * @var JobRepositoryInterface
     */
    protected $jobRepository;

    /**
     * @var ProductRepositoryInterface
     */
    protected $productRepository;

    /**
     * @var \Magento\Framework\Filesystem\Driver\File
     */
    protected $driverFile;

    /**
     * @var \Firebear\ImportExport\Test\Integration\Helpers\JobFixturesManager
     */
    protected $jobFixtureManager;

    /**
     * @var Data
     */
    protected $helper;

    /**
     * @var Processor
     */
    protected $processor;

    /**
     * @var Filesystem
     */
    protected $filesystem;

    protected function setUp(): void
    {
        /** @phpstan-ignore-next-line */
        $this->objectManager = Bootstrap::getObjectManager();
        $this->jobRepository = $this->objectManager->get(JobRepositoryInterface::class);
        $this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class);
        $this->driverFile = $this->objectManager->get(\Magento\Framework\Filesystem\Driver\File::class);
        $this->jobFixtureManager = $this->objectManager->get(
            \Firebear\ImportExport\Test\Integration\Helpers\JobFixturesManager::class
        );
        $this->helper = $this->objectManager->get(Data::class);
        $this->processor = $this->objectManager->get(Processor::class);
        $this->filesystem = $this->objectManager->get(Filesystem::class);
    }

    /**
     * @param string $sourcePath
     * @param string $destPath
     * @throws \Magento\Framework\Exception\FileSystemException
     */
    protected function copyFile(string $sourcePath, string $destPath)
    {
        if (!$this->driverFile->isExists($sourcePath)) {
            throw new Exception('File not found. Path: ' . $sourcePath);
        }

        if (!$this->driverFile->isWritable(dirname($destPath))) {
            $this->driverFile->createDirectory(dirname($destPath));
        }

        if (!$this->driverFile->copy($sourcePath, $destPath)) {
            throw new Exception('Failed to copy file');
        }
    }

    /**
     * @return \Magento\Catalog\Api\Data\ProductSearchResultsInterface
     */
    protected function getAllProducts()
    {
        /** @var SearchCriteriaBuilder $searchCriteriaBuilder */
        $searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class);
        return $this->productRepository->getList($searchCriteriaBuilder->create());
    }

    /**
     * @param $jobId
     * @return bool|string
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    protected function runExport($jobId)
    {
        $file = $this->helper->beforeRun($jobId);
        $history = $this->helper->createExportHistory($jobId, $file, 'console');
        $this->processor->debugMode = $this->helper->getDebugMode();
        $this->processor->setLogger($this->helper->getLogger());
        $this->processor->inConsole = 1;
        $this->processor->process($jobId, $history);
        return $this->getFileContent($history->getTempFile());
    }

    /**
     * Get fileContent
     *
     * @param int $historyId
     * @return array|string
     * @throws \Magento\Framework\Exception\FileSystemException
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    protected function getFileContent($file)
    {
        $fileContent = [];
        $dir = $this->filesystem->getDirectoryWrite(DirectoryList::ROOT);
        if (!empty($file)) {
            $path = $dir->getAbsolutePath($file);
            $fileContent = $dir->readFile($path);
            if (!empty($fileContent)) {
                $fileContent = $this->parseData($fileContent);
            }
        }
        return $fileContent;
    }

    /**
     * Parse Data
     *
     * @param string $fileContent
     * @return array
     */
    protected function parseData($fileContent)
    {
        $data = [];
        $rows = explode("\n", $fileContent);
        $headers = str_getcsv(array_shift($rows));

        foreach ($rows as $row) {
            if (empty($row)) {
                continue;
            }
            $rowData = str_getcsv($row);
            $row = [];
            foreach ($headers as $index => $header) {
                $row[$header] = isset($rowData[$index]) ? $rowData[$index] : '';
            }
            $data[] = $row;
        }
        return $data;
    }
}
