<?php
declare(strict_types=1);

namespace FiloBlu\Refilo\Model\Importer;

use FiloBlu\Refilo\Helper\Data;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\File\Csv;
use Magento\Framework\Filesystem;
use Magento\Framework\Filesystem\Directory\Write;
use Magento\Framework\HTTP\Client\Curl;
use Magento\Framework\Math\Random;
use Magento\Framework\Module\Dir;
use Magento\Translation\Model\ResourceModel\StringUtils;
use Magento\Translation\Model\ResourceModel\Translate;

/**
 * Class Translation
 * @package FiloBlu\Refilo\Model\Importer
 */
class Translation
{
    /**
     * @var Dir
     */
    private $moduleDirectory;
    /**
     * @var Csv
     */
    private $csv;
    /**
     * @var Translate
     */
    private $resourceTranslate;
    /**
     * @var StringUtils
     */
    private $stringUtils;
    /**
     * @var Curl
     */
    private $curl;
    /**
     * @var ScopeConfigInterface
     */
    private $config;
    /**
     * @var Filesystem
     */
    private $filesystem;
    /**
     * @var Data
     */
    private $helper;

    /**
     * Translation constructor.
     * @param Dir $moduleDirectory
     * @param Csv $csv
     * @param Translate $resourceTranslate
     * @param StringUtils $stringUtils
     * @param Curl $curl
     * @param Filesystem $filesystem
     * @param ScopeConfigInterface $config
     * @param Data $helper
     */
    public function __construct(
        Dir                  $moduleDirectory,
        Csv                  $csv,
        Translate            $resourceTranslate,
        StringUtils          $stringUtils,
        Curl                 $curl,
        Filesystem           $filesystem,
        ScopeConfigInterface $config,
        Data                 $helper
    )
    {
        $this->moduleDirectory = $moduleDirectory;
        $this->csv = $csv;
        $this->resourceTranslate = $resourceTranslate;
        $this->stringUtils = $stringUtils;
        $this->curl = $curl;
        $this->config = $config;
        $this->filesystem = $filesystem;
        $this->helper = $helper;
    }

    /**
     * @param string $locale
     */
    public function import(string $locale)
    {
        foreach ($this->getTranslationsToAdd($locale) as $string => $translate) {
            $this->stringUtils->saveTranslate($string, $translate, $locale, 0);
        }
    }

    /**
     * @param string $locale
     * @return void
     */
    public function importFromFileOnly(string $locale)
    {
        foreach ( array_diff_key($this->loadFormFile($locale), $this->loadFromDatabase($locale)) as $string => $translate) {
            $this->stringUtils->saveTranslate($string, $translate, $locale, 0);
        }
    }

    /**
     * @param string $locale
     * @return array
     */
    public function getTranslationsToAdd(string $locale)
    {
        $storeFrontTranslations = $this->loadFromStoreFront();
        $requiredTranslations = array_merge($storeFrontTranslations, $this->loadFormFile($locale));

        // Update is_frontend_label for storefront labels
        $table = $this->resourceTranslate->getMainTable();
        $keys = array_unique(array_keys($requiredTranslations));
        $conection = $this->resourceTranslate->getConnection();
        $conection->update($table, ['is_frontend_label' => '0']);
        $chunks = array_chunk($keys, 1000);

        foreach ($chunks as $chunk) {
            $conection->update($table, ['is_frontend_label' => '1'], ['string IN (?)' => $chunk]);
        }
        // End update for is_frontend_label
        
        return array_diff_key($requiredTranslations, $this->loadFromDatabase($locale));
    }

    /**
     *
     */
    public function loadFromStoreFront()
    {
        $baseUrl = $this->helper->getStoreFrontBaseUrl(0);

        if (!$baseUrl) {
            return [];
        }

        $url = trim($baseUrl, '/') . '/translations';

        // TODO: Handle https certificate validation via flag
        $this->curl->setOption(CURLOPT_SSL_VERIFYHOST, false);
        $this->curl->setOption(CURLOPT_SSL_VERIFYPEER, false);
        $this->curl->setOption(CURLOPT_FOLLOWLOCATION, 1);
        $this->curl->setOption(CURLOPT_MAXREDIRS, 10);

        $this->curl->get($url);

        // TODO: provide some form of logging
        if (!in_array((int)$this->curl->getStatus(),[200,301])) {
            return [];
        }

        $body = $this->curl->getBody();

        /** @var Write $directory */
        $directory = $this->filesystem->getDirectoryWrite(
            DirectoryList::TMP
        );

        $directory->create();

        $tmpFileName = $directory->getAbsolutePath(
            'store_front_lables' . uniqid((string)Random::getRandomNumber()) . time() . '.csv'
        );

        file_put_contents($tmpFileName, $body);

        $translations = $this->csv->getDataPairs($tmpFileName);

        array_shift($translations);

        $directory->delete($directory->getRelativePath($tmpFileName));
        return $translations;
    }

    /**
     * @param string $locale
     * @return array
     */
    public function loadFormFile(string $locale): array
    {
        $root = $this->moduleDirectory->getDir('FiloBlu_Refilo');
        $translationsFile = implode(DIRECTORY_SEPARATOR, [$root, 'labels', "{$locale}.csv"]);
        return $this->csv->getDataPairs($translationsFile) ?? [];
    }

    /**
     * @param string $locale
     * @return array
     */
    public function loadFromDatabase(string $locale): array
    {
        return $this->resourceTranslate->getTranslationArray(0, $locale) ?? [];
    }
}
