<?php

namespace PrestaShop\Module\PolarisPrestaConnector\Controller;

use PrestaShop\Module\PolarisPrestaConnector\SyncConfiguration;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use PrestaShop\Module\PolarisPrestaConnector\Syncer;

class ConfigurationAjaxAdminController extends AdminController
{
    /**
     * Méthode qui est appelée depuis un code Web2 pour vérifier :
     * - (param `address`) : soit que l'URL pointe bien vers le backoffice
     * - (param `address`, `fingerprint`) : soit que si le certificat est autosigné sur une URL correcte, il est correct
     * - (param `address`, `fingerprint`, `username`, `password`) : soit que les informations de login sont corrects sur un certificat accepté, sur une URL correcte
     * 
     * La méthode autodétecte ce qu'il y a à faire selon les paramètres fourni et renvoi :
     * - { } : tout vas bien
     * - { "fingerprint" : "" } tout vas bien mais le certificat est autosigné et il faut vérifier le fingerprint
     * - { "error" : "" } : il s'agit du message d'erreur
     */
    public function connectToApiAjaxAction(Request $request)
    {
        // On récupère le bridge
        $bridge = $this->module->getBridge();

        // On délègue le traitement à la méthode du bridge
        $errorMsg = $bridge->bind([
                        "address" => $request->get('address'),
                        "fingerprint" => $request->get('fingerprint'),
                        "username" => $request->get('username'),
                        "password" => $request->get('password'),
                        "pincode" => $request->get('pincode'),
                        ]);                    

        if ($errorMsg)
        {
            // Si le message commence par un chiffre, alors c'est un code d'erreur, on l'isole
            $code = (int) preg_replace('/^(\d+).*/', '$1', $errorMsg) ?? 0;
            preg_match('/Empreinte : ([a-f0-9]{40,})/', $errorMsg, $matches);
            $fingerprint = $matches[1] ?? null;
            // Et on retire le code du message original
            $errorMsg = preg_replace('/^\d+ : /', '', $errorMsg) ?? $errorMsg;
            // Et s'il y a l'empreinte on la retire du message original
            $errorMsg = preg_replace('/Empreinte : [a-f0-9]{40,}/', '', $errorMsg) ?? $errorMsg;
            // Le message d'erreur doit commencer par une majuscule
            $errorMsg = ucfirst($errorMsg);
            return new JsonResponse(['success' => false, 'code' => $code, 'message' => $errorMsg , 'fingerprint' => $fingerprint]);
        }
        else
            return new JsonResponse(['success' => true, 'message' => '']);
    }   
    
    /**
     * Synchronisation d'un produit
     */
    public function syncProductAjaxAction(Request $request)
    {
        try
        {
            // Fin de la session pour éviter de bloquer le processus et les autres demande du même utilisateur
            if (session_id()) 
                session_write_close();
            
            // On va intercepter toutes les sorties
            ob_start();

            // On instancie un syncer
            $syncer = new Syncer($this->module, true);

            // On délègue le traitement à la méthode du syncer            
            $syncer->syncProduct($request->get('id_product'));

            // On encapule le résultat dans la sortie
            $output = ob_get_clean();

            // Si tout est bon on renvoi un message de succès
            return new JsonResponse(['success' => (strpos($output, 'ERR') === false), 'message' => $output]);
        }
        catch (\Exception $e)
        {            
            return new JsonResponse(['success' => false, 'message' => $e->getMessage()]);
        }
    }

    /**
     * Exportation d'une commande
     */
    public function exportOrderAjaxAction(Request $request)
    {
        try
        {
            // Fin de la session pour éviter de bloquer le processus et les autres demande du même utilisateur
            if (session_id()) 
                session_write_close();

            // On instancie un syncer
            $syncer = new Syncer($this->module);

            // On délègue le traitement à la méthode du syncer
            $syncer->exportOrder($request->get('order_reference'));

            // Si tout est bon on renvoi un message de succès
            return new JsonResponse(['success' => true, 'message' => '']);
        }
        catch (\Exception $e)
        {
            return new JsonResponse(['success' => false, 'message' => $e->getMessage()]);
        }
    }

    /**
     * Verrouillage d'un produit
     */
    public function lockProductAjaxAction(Request $request)
    {
        try
        {
            $action = $request->get('action');
            $id_product = $request->get('id_product');

            if ($action == "lock")
                $this->module->getCfg()->lockProduct($id_product);
            else
                $this->module->getCfg()->unlockProduct($id_product);

            // Si tout est bon on renvoi un message de succès
            return new JsonResponse(['success' => true, 'message' => '']);
        }
        catch (\Exception $e)
        {
            return new JsonResponse(['success' => false, 'message' => $e->getMessage()]);
        }
    }

    /**
     * Programme une resynchronisation totale
     */
    public function syncResyncAction(Request $request)
    {
        try
        {
            // On instancie un syncer
            $syncer = new Syncer($this->module);
            $cfg = $this->module->getCfg();

            // Demande de resynchronisation totale pour la prochaine fois
            $syncer->bridge->resetSyncPosition();

            // On marque toutes les synchronisations comme jamais effectuées (Fix #142)
            $cfg->set(SyncConfiguration::CFG_SYNCS_LAST, []);

            // On appelle une URL mais on attend pas la réponse (cela permet de lancer le processus en tâche de fond)
            // URL à appeler : le contrôleur front cron
            // avec curl ?
            $url = \Context::getContext()->link->getModuleLink($this->module->name, 'cron', ['guard' => $cfg->get(SyncConfiguration::CFG_GUARD_TOKEN) ], true);

            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
            curl_setopt($ch, CURLOPT_TIMEOUT_MS, 5000); // on coupe vite
            curl_setopt($ch, CURLOPT_NOBODY, true);  // on ne lit pas le corps
            curl_exec($ch);
            curl_close($ch);


            // Si tout est bon on renvoi un message de succès
            return new JsonResponse(['success' => true, 'message' => '']);
        }
        catch (\Exception $e)
        {
            return new JsonResponse(['success' => false, 'message' => $e->getMessage()]);
        }
    }

    /**
     * Obtient la progression de la synchronisation en cours ou null si aucune synchronisation en cours
     */
    public function getSyncProgressAjaxAction()
    {
        try
        {
            // On récupère la progression sans instancier (on gagne du temps)
            $progress = Syncer::getSyncProgress($this->module);

            // Si tout est bon on renvoi un message de succès
            return new JsonResponse(['success' => true, 'progress' => $progress->toArray()]);
        }
        catch (\Exception $e)
        {
            return new JsonResponse(['success' => false, 'message' => $e->getMessage()]);
        }
    }

    
    /**
     * Tirage de l'environnement
     */
    public function pullenvAjaxAction() 
    {
        try
        {            
            // Tirage de l'environnement
            $this->module->getBridge()->pullEnvironment(true);

            // Si tout est bon on renvoi un message de succès
            return new JsonResponse(['success' => true]);
        }
        catch (\Exception $e)
        {
            return new JsonResponse(['success' => false, 'message' => $e->getMessage()]);
        }
    }

}