<?php

namespace Myvetshop\Module\Clinique\Command\Click2Buy;

use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class GenerateCommand extends Command
{
    protected const QUERY_LIMIT = 500;

    protected EntityManagerInterface $entityManager;

    public function __construct(EntityManagerInterface $entityManager)
    {
        parent::__construct('app:c2b:generate');

        $this->entityManager = $entityManager;
    }

    protected function configure(): void
    {
        $this->setDescription('Génère les fichiers nécessaires à Click2Buy (pour Virbac)');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $dir = $this->createDirIfNotExists();
        $connexion = $this->entityManager->getConnection();

        $queries = [
            'stores' => 'SELECT'
                . ' c.code_privilege AS outlet_id'
                . ', c.name AS retailer_name'
                . ', c.name AS outlet_name'
                . ', TRIM(" - " FROM CONCAT(sl.address1, " - ", sl.address2)) AS address'
                . ', s.postcode AS zip_code'
                . ', s.city AS town'
                . ', co.iso_code AS country_code'
                . ', s.latitude AS latitude'
                . ', s.longitude AS longitude'
                . ', sl.hours AS open_hours'
                . ' FROM ps_myvetshop_clinique c'
                . ' INNER JOIN ps_store s ON s.id_store=c.id_store'
                . ' INNER JOIN ps_store_lang sl ON sl.id_store=s.id_store AND sl.id_lang=1'
                . ' INNER JOIN ps_country co ON co.id_country=s.id_country',
            'products' => 'SELECT'
                . ' pa.id_product_attribute AS product_id'
                . ', pa.ean13 AS ean'
                . ', TRIM("()" FROM CONCAT(pl.name, "(", GROUP_CONCAT(al.name SEPARATOR ", "), ")") COLLATE utf8mb4_general_ci) AS product_name'
                . ', pa.tarif_privilege AS price'
                . ', m.name AS brand'
                . ', pa.id_product AS image'
                . ', pa.id_product AS url'
                . ' FROM ps_product_attribute pa'
                . ' INNER JOIN ps_product_lang pl ON pl.id_product=pa.id_product AND pl.id_lang=1 AND pl.id_shop=1'
                . ' INNER JOIN ps_product_attribute_combination pac ON pac.id_product_attribute=pa.id_product_attribute'
                . ' INNER JOIN ps_attribute_lang al ON al.id_attribute=pac.id_attribute AND al.id_lang=1'
                . ' INNER JOIN ps_product p ON p.id_product=pa.id_product'
                . ' INNER JOIN ps_manufacturer m ON m.id_manufacturer=p.id_manufacturer'
                . ' GROUP BY pa.id_product_attribute',
            'store_products' => 'SELECT'
                . ' s.id_product_attribute AS product_id'
                . ', c.code_privilege AS outlet_id'
                . ', s.physical_quantity > 0 AS availability'
                . ', pa.tarif_privilege AS price'
                . ' FROM ps_stock s'
                . ' INNER JOIN ps_myvetshop_clinique c ON c.id_warehouse=s.id_warehouse'
                . ' INNER JOIN ps_product_attribute pa ON pa.id_product_attribute=s.id_product_attribute',
        ];

        foreach ($queries as $name => $query) {
            $countQuery = \preg_replace('#^(SELECT) .+ (FROM .+)$#', '$1 COUNT(*) $2', $query);
            \assert(\is_string($countQuery));
            $count = $connexion->executeQuery($countQuery)->fetch();
            \assert(\is_numeric($count));
            $pages = \ceil((int) $count / self::QUERY_LIMIT);
            $stream = \fopen($dir . '/' . $name . '.csv', 'w');
            if (!$stream) {
                throw new \LogicException(\sprintf('Cannot open the %s file', $name));
            }

            $addHeaders = true;
            for ($i = 1; $i <= $pages; ++$i) {
                $offset = ($i - 1) * self::QUERY_LIMIT;
                $finalQuery = $query . ' LIMIT ' . self::QUERY_LIMIT . ' OFFSET ' . $offset;
                foreach ($connexion->executeQuery($finalQuery)->fetchAll() as $row) {
                    \assert(\is_array($row));
                    if ($addHeaders) {
                        \fputcsv($stream, \array_keys($row));
                    }
                    $addHeaders = false;

                    switch ($name) {
                        case 'products':
                            $product = new \Product($row['image'], false, 1, 1);
                            $row['image'] = (new \Link())->getImageLink(
                                \is_array($product->link_rewrite) ? ($product->link_rewrite[0] ?? '') : $product->link_rewrite,
                                // @phpstan-ignore-next-line
                                \Image::getCover($product->id)['id_image'],
                                'home_default',
                            );
                            \strpos($row['image'], 'http') === 0 ?: $row['image'] = 'https://' . $row['image'];
                            $row['url'] = (new \Link())->getProductLink($product);
                            break;
                    }

                    \fputcsv($stream, $row);
                }
            }
            \fclose($stream);
        }

        return 0;
    }

    protected function createDirIfNotExists(): string
    {
        $dir = _PS_ROOT_DIR_ . '/Click2Buy';
        if (!\is_dir($dir)) {
            \mkdir($dir);
        }

        $indexPath = $dir . '/index.php';
        $htaccessPath = $dir . '/.htaccess';
        $htpasswdPath = $dir . '/.htpasswd';

        // Création d'un index.php pour éviter le listing
        if (!\file_exists($indexPath)) {
            \file_put_contents($indexPath, '');
        }

        // Création d'un htaccess pour limiter l'accès
        if (!\file_exists($htaccessPath)) {
            $stream = \fopen($htaccessPath, 'w');
            if (!$stream) {
                throw new \LogicException('Cannot open the htaccess file');
            }

            \fwrite($stream, 'AuthType Basic' . "\n");
            \fwrite($stream, 'AuthName "Accès protégé"' . "\n");
            \fwrite($stream, 'AuthUserFile ' . $dir . '/.htpasswd' . "\n");
            \fwrite($stream, 'require valid-user' . "\n");
            \fclose($stream);
        }

        // Création d'un htpasswd pour définir les accès
        if (!\file_exists($htpasswdPath)) {
            \file_put_contents($htpasswdPath, 'c2b:$apr1$0641a7gp$HytFbulVG05Cm8Oo6fTzJ/');
        }

        return $dir;
    }
}
