<?php

namespace Modules\API\APIExterne\Controller;

use API\Bouyco\Bouyco;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Exception\ServerException;
use GuzzleHttp\Psr7\Response;
use Helpers\Fichier\Fichier;
use Helpers\Log\LogSysteme;
use Helpers\Outil\Outils;
use Helpers\Trad\Trad;
use Skeleton\Controller\Controller;

class BouycoController extends Controller
{
    
    /**
     * init
     *
     * @return void
     */
    public function init()
    {
        set_time_limit(600);
        ini_set('memory_limit', '500M');
    }

    /**
     * @param array<mixed> $post
     * @param string $nomFichierRetour
     * @return void
     */
    public function dispatcher($post, $nomFichierRetour)
    {
        $paramFileName = $post[0];

        $return = [
            'codeHttp' => 400,
            'data' => [
                'statut' => 'N',
                'message' => ''
            ]
        ];

        if (!Fichier::fileExisteTmp($paramFileName)) {
            $return['data']['message'] = 'Le fichier est introuvable dans le dossier tmp.';
        } else {
            $content = Fichier::getContentFile($paramFileName);
            // @phpstan-ignore-next-line
            if (substr($content, 0, 3) === pack('CCC', 0xEF, 0xBB, 0xBF)) {
                $content = substr((string) $content, 3);
            }

            if (!Outils::isJson((string) $content)) {
                $return['data']['message'] = 'Le fichier de paramètre n\'est pas au format json.';
            } else {
                $params     = json_decode((string) $content, true) ?? [];

                if (!isset($params['action'])) {
                    $return['data']['message'] = 'Le paramètre action est manquant ou invalide.';
                } else {
                    $action = $params['action'];

                    if ($action === 'E') {
                        $apiBouyco  = new Bouyco($this->pdo, $nomFichierRetour, true);
                        $return = $this->exportAction($apiBouyco, $params);
                    } else {
                        $apiBouyco  = new Bouyco($this->pdo, $nomFichierRetour);
                        $return = $this->importAction($apiBouyco, $params);
                    }
                }
            }
        }

        if (isset($apiBouyco)) {
            $apiBouyco->createReturnFile($return);
        } else {
            Fichier::createFichierTmp($nomFichierRetour, $return['codeHttp'].'|'.$return['data']['message']);
        }
    }

    /**
     * @param Bouyco $apiBouyco
     * @param array<mixed> $params
     * @return array<mixed>
     */
    /*public function importAction() // mode debug
    {

        $apiBouyco  = new Bouyco($this->pdo, 'testmsa1');
        $params = [
            'mode' => 'test',
            'dateDebut' => '20240905',
            'dateFin' => '20240905',
            'codeLng' => 'FR',
            'action' => 'I',
            'module' => 'FOURNISS',
            'codeLegacy' => 'HG',
            'FichierIn' => [
                'C__Oxalys226_Oxadata_tmp_48665324361728038471604935.json'
            ],
            'FichierOut' => 'msa.json',
        ];*/
    public function importAction($apiBouyco, $params)
    {
        $authorizedMode = [
            'test',
            'api',
        ];

        $return = [
            'codeHttp' => 400,
            'data' => [
                'statut' => 'N',
                'message' => ''
            ]
        ];

        $mode = $params['mode'];
        $module = $params['module'];
        $functionName = 'import'.ucfirst($module).'Action';

        if (!in_array($mode, $authorizedMode)) {
            $return['data']['message'] = 'Le mode demandé n\'est pas autorisé.';
        } elseif (empty($params['codeLng'])) {
            $return['data']['message'] = 'Le paramètre codeLng (code langue) est manquant ou vide.';
        } elseif (empty($params['codeLegacy'])) {
            $return['data']['message'] = 'Le paramètre codeLegacy (code site) est manquant ou vide.';
        } elseif (empty($params['dateDebut'])) {
            $return['data']['message'] = 'Le paramètre dateDebut est manquant ou vide.';
        } elseif (empty($params['dateFin'])) {
            $return['data']['message'] = 'Le paramètre dateFin est manquant ou vide.';
        } elseif (empty($params['FichierOut'])) {
            $return['data']['message'] = 'Le paramètre FichierOut est manquant ou vide.';
        } elseif ($mode === 'test' && empty($params['FichierIn'])) {
            $return['data']['message'] = 'Le paramètre FichierIn est manquant ou vide pour le mode test.';
        } elseif ($apiBouyco->hasError()) {
            switch ($apiBouyco->getCodeError()) {
                case "missingParams":
                    $return['data']['message'] = Trad::strBuild(
                        'Les paramètres @1@ sont vides ou manquant dans la base de donnée.',
                        implode(', ', $apiBouyco->getDataError())
                    );
                    break;

                default:
                    $return['data']['message'] = 'Une erreur PHP s\'est produite avec l\'API';
                    break;
            }
        } else {
            if (method_exists($this, $functionName)) {
                $return = $this->$functionName($apiBouyco, $params);
            } else {
                $return['data']['message'] = 'Le module d\'import demandé pour la requête API n\'existe pas.';
            }
        }

        return $return;
    }

    /**
     * @param Bouyco $apiBouyco
     * @param array<mixed> $params
     * @return array<mixed>
     */
    public function exportAction($apiBouyco, $params)
    {
        $return = [
            'codeHttp' => 400,
            'data' => [
                'statut' => 'N',
                'message' => ''
            ]
        ];

        $module     = $params['module'];
        $checkToken = $apiBouyco->checkToken();

        $functionName = 'export'.ucfirst($module).'Action';


        if (empty($params['FichierIn'])) {
            $return['data']['message'] = 'Le paramètre FichierIn est vide ou n\'existe pas. Au moins 1 fichier doit être transféré.';
        } elseif ($checkToken['availability'] === false) {
            switch ($checkToken['code']) {
                case "tokenNotExist":
                    $return['data']['message'] = 'Le token n\'existe pas, merci d\'en générer un.';
                    break;

                case "tokenExpired":
                    $return['data']['message'] = 'Le token a expiré. Merci d\'en générer un nouveau.';
                    break;
            }
        } else {
            if (method_exists($this, $functionName)) {
                $return = $this->$functionName($apiBouyco, $params);
            } else {
                $return['data']['message'] = 'Le module d\'export demandé pour la requête API n\'existe pas.';
            }
        }

        return $return;
    }

    /**
     * @param Bouyco $apiBouyco
     * @param array<mixed> $params
     * @return array<mixed>
     * @throws GuzzleException
     */
    public function importOiaAction(Bouyco $apiBouyco, array $params)
    {
        $return     = [
            'codeHttp'  => 400,
            'data'      => [
                'statut'    => 'N',
                'message'   => '',
            ]
        ];

        $mode = $params['mode'];

        if ($mode === 'test') {
            $files = $params['FichierIn'];

            foreach ($files as $file) {
                if (Fichier::fileExisteTmp($file)) {
                    $dataFile = (string) Fichier::getContentFile($file);

                    // @phpstan-ignore-next-line
                    if (substr($dataFile, 0, 3) === pack('CCC', 0xEF, 0xBB, 0xBF)) {
                        $dataFile = substr($dataFile, 3);
                    }

                    if (Outils::isJson($dataFile)) {
                        $resultImportFile = $apiBouyco->importOiaByFile($dataFile);

                        if (!$resultImportFile) {
                            $return['data']['message'] .= Trad::strBuild(
                                "Le fichier @1@ ne comporte pas la bonne structure de fichier.",
                                $file
                            );
                        } else {
                            $return['codeHttp'] = 200;
                            $return['data']['statut']   = 'O';
                            $return['data']['message'] .= Trad::strBuild(
                                "Le fichier @1@ a bien été importé.",
                                $file
                            );
                        }
                    } else {
                        $return['data']['message'] .= Trad::strBuild(
                            "Le fichier @1@ pour l'import direct n'est pas au format json.",
                            $file
                        );
                    }
                } else {
                    $return['data']['message'] .= Trad::strBuild(
                        "Le fichier @1@ pour l'import direct est introuvable.",
                        $file
                    );
                }
            }
        } elseif ($mode === 'api') {
            $initParams = [
                '$format' => 'json',
                '$skip' => 0,
                '$top' => $apiBouyco->nbOiaPerPage,
                '$expand' => 'entete,steNbrOia',
                '$filter' => "(mode eq 'A' and appCode eq '{$params['codeLegacy']}' and dateDebutMaj eq '{$params['dateDebut']}' and dateFinMaj eq'{$params['dateFin']}')",
            ];
            $result = $apiBouyco->importOia($initParams, $params);

            $return = $apiBouyco->getReturn($result, $params);
        }

        if (($apiBouyco->hasError())) {
            $codeError = $apiBouyco->getCodeError();
            if ($codeError === 'error_log') {
                $return['data']['message'] = 'Un fichier de log a été généré suite à une erreur lors de la requête API';
            }
        }

        return $return;
    }

    /**
     * @param Bouyco $apiBouyco
     * @param array<mixed> $params
     * @return array<mixed>
     * @throws GuzzleException
     */
    public function importOrderBlockedAction(Bouyco $apiBouyco, array $params)
    {
        $return     = [
            'codeHttp'  => 400,
            'data'      => [
                'statut'    => 'N',
                'message'   => '',
            ]
        ];

        $mode = $params['mode'];

        if ($mode === 'test') {
            $files = $params['FichierIn'];

            foreach ($files as $file) {
                if (Fichier::fileExisteTmp($file)) {
                    $dataFile = (string) Fichier::getContentFile($file);

                    // @phpstan-ignore-next-line
                    if (substr($dataFile, 0, 3) === pack('CCC', 0xEF, 0xBB, 0xBF)) {
                        $dataFile = substr($dataFile, 3);
                    }

                    if (Outils::isJson($dataFile)) {
                        $resultImportFile = $apiBouyco->importOrderBlockedByFile($dataFile);

                        if (!$resultImportFile) {
                            $return['data']['message'] .= Trad::strBuild(
                                "Le fichier @1@ ne comporte pas la bonne structure de fichier.",
                                $file
                            );
                        } else {
                            $return['codeHttp'] = 200;
                            $return['data']['statut']   = 'O';
                            $return['data']['message'] .= Trad::strBuild(
                                "Le fichier @1@ a bien été importé.",
                                $file
                            );
                        }
                    } else {
                        $return['data']['message'] .= Trad::strBuild(
                            "Le fichier @1@ pour l'import direct n'est pas au format json.",
                            $file
                        );
                    }
                } else {
                    $return['data']['message'] .= Trad::strBuild(
                        "Le fichier @1@ pour l'import direct est introuvable.",
                        $file
                    );
                }
            }
        } elseif ($mode === 'api') {
            $initParams = [
                '$format'   => 'json',
                '$skip'     => 0,
                '$top'      => $apiBouyco->nbOiaPerPage,
                '$expand'   => 'entete,cdeBlc',
                '$filter'   => "(appCode eq '{$params['codeLegacy']}' and dateDebutMaj eq '{$params['dateDebut']}' and dateFinMaj eq'{$params['dateFin']}')",
            ];
            $result = $apiBouyco->importOrderBlocked($initParams, $params);

            $return = $apiBouyco->getReturn($result, $params);
        }

        if (($apiBouyco->hasError())) {
            $codeError = $apiBouyco->getCodeError();
            if ($codeError === 'error_log') {
                $return['data']['message'] = 'Un fichier de log a été généré suite à une erreur lors de la requête API';
            }
        }

        return $return;
    }


    /**
     * @param Bouyco $apiBouyco
     * @param array<mixed> $params
     * @return array<mixed>
     * @throws GuzzleException
     */
    public function importFournissAction(Bouyco $apiBouyco, array $params)
    {
        $return     = [
            'codeHttp'  => 400,
            'data'      => [
                'statut'    => 'N',
                'message'   => '',
            ]
        ];

        $mode = $params['mode'];

        if ($mode === 'test') {
            $files = $params['FichierIn'];

            foreach ($files as $file) {
                if (Fichier::fileExisteTmp($file)) {
                    $dataFile = (string) Fichier::getContentFile($file);

                    // @phpstan-ignore-next-line
                    if (substr($dataFile, 0, 3) === pack('CCC', 0xEF, 0xBB, 0xBF)) {
                        $dataFile = substr($dataFile, 3);
                    }

                    if (Outils::isJson($dataFile)) {
                        $resultImportFile = $apiBouyco->importFournissByFile($dataFile);

                        if (!$resultImportFile) {
                            $return['data']['message'] .= Trad::strBuild(
                                "Le fichier @1@ ne comporte pas la bonne structure de fichier.",
                                $file
                            );
                        } else {
                            $return['codeHttp'] = 200;
                            $return['data']['statut']   = 'O';
                            $return['data']['message'] .= Trad::strBuild(
                                "Le fichier @1@ a bien été importé.",
                                $file
                            );
                        }
                    } else {
                        $return['data']['message'] .= Trad::strBuild(
                            "Le fichier @1@ pour l'import direct n'est pas au format json.",
                            $file
                        );
                    }
                } else {
                    $return['data']['message'] .= Trad::strBuild(
                        "Le fichier @1@ pour l'import direct est introuvable.",
                        $file
                    );
                }
            }
        } elseif ($mode === 'api') {
            $initParams = [
                '$format' => 'json',
                '$filter' => "(dateDebut eq '{$params['dateDebut']}' and dateFin eq '{$params['dateFin']}')",
                '$expand' => 'navHd,navFrn/navOrg,navFrn/navCnt',
                '$top'    => $apiBouyco->nbOiaPerPage,
                '$skip'   => 0
            ];
            $result = $apiBouyco->importFourniss($initParams, $params);

            $return = $apiBouyco->getReturn($result, $params);
        }

        if (($apiBouyco->hasError())) {
            $codeError = $apiBouyco->getCodeError();
            if ($codeError === 'error_log') {
                $return['data']['message'] = 'Un fichier de log a été généré suite à une erreur lors de la requête API';
            }
        }

        return $return;
    }

    /**
     * @param Bouyco $apiBouyco
     * @param array<mixed> $params
     * @return array<mixed>
     */
    public function exportCommandesAction(Bouyco $apiBouyco, array $params)
    {
        $files      = $params['FichierIn'];
        $return     = [
            'codeHttp'  => 400,
            'data'      => [
                'statut'    => 'N',
                'message'   => '',
            ]
        ];

        foreach ($files as $file) {
            if (Fichier::fileExisteTmp($file)) {
                $dataFile = (string) Fichier::getContentFile($file);

                // @phpstan-ignore-next-line
                if (substr($dataFile, 0, 3) === pack('CCC', 0xEF, 0xBB, 0xBF)) {
                    $dataFile = substr($dataFile, 3);
                }

                if (Outils::isJson($dataFile)) {
                    $res = $apiBouyco->exportCdes($dataFile);

                    if ($res instanceof ClientException || $res instanceof ServerException) {
                        $body = (string)$res->getResponse()->getBody();
                        $body = json_decode($body, true);
                        $message = $body['error']['message']['value'];

                        $return = [
                            'codeHttp'  => $res->getCode(),
                            'data'      => [
                                'statut'    => 'N',
                                'message'   => $message,
                            ]
                        ];
                    } else {
                        $status = $res->getStatusCode();

                        if ($status === 201) {
                            $return['codeHttp'] = 200;
                            $return['data']['statut'] = 'O';
                            $return['data']['message'] .= Trad::strBuild(
                                'Le fichier @1@ a bien été exporté.',
                                $file
                            );

                            $body = json_decode($res->getBody(), true);

                            $rejectedData = $body['navRejectedObject'] ?? [];
                            $apiBouyco->treatRejectedData($rejectedData);
                        } else {
                            $return['data']['message'] .= Trad::strBuild(
                                'Le fichier @1@ n\'a pas été exporté.',
                                $file
                            );
                        }
                    }
                } else {
                    $return['data']['message'] .= Trad::strBuild(
                        "Le fichier @1@ pour l'export n'est pas au format json.",
                        $file
                    );
                }
            } else {
                $return['data']['message'] .= Trad::strBuild(
                    "Le fichier @1@ pour l'export est introuvable.",
                    $file
                );
            }
        }

        return $return;
    }

    /**
     * @param Bouyco $apiBouyco
     * @param array<mixed> $params
     * @return array<mixed>
     */
    public function exportReceptionsAction(Bouyco $apiBouyco, array $params)
    {
        $files      = $params['FichierIn'];
        $return     = [
            'codeHttp'  => 400,
            'data'      => [
                'statut'    => 'N',
                'message'   => '',
            ]
        ];

        foreach ($files as $file) {
            if (Fichier::fileExisteTmp($file)) {
                $dataFile = (string) Fichier::getContentFile($file);

                // @phpstan-ignore-next-line
                if (substr($dataFile, 0, 3) === pack('CCC', 0xEF, 0xBB, 0xBF)) {
                    $dataFile = substr($dataFile, 3);
                }

                if (Outils::isJson($dataFile)) {
                    $res = $apiBouyco->exportReceipt($dataFile);

                    if ($res instanceof ClientException || $res instanceof ServerException) {
                        $body = (string)$res->getResponse()->getBody();
                        $body = json_decode($body, true);
                        $message = $body['error']['message']['value'];

                        $return = [
                            'codeHttp'  => $res->getCode(),
                            'data'      => [
                                'statut'    => 'N',
                                'message'   => $message,
                            ]
                        ];
                    } else {
                        $status = $res->getStatusCode();

                        if ($status === 201) {
                            $return['codeHttp'] = 200;
                            $return['data']['statut'] = 'O';
                            $return['data']['message'] .= Trad::strBuild(
                                'Le fichier @1@ a bien été exporté.',
                                $file
                            );

                            $body = json_decode($res->getBody(), true);

                            $rejectedData = $body['navRejectedObject'] ?? [];
                            $apiBouyco->treatRejectedData($rejectedData);
                        } else {
                            $return['data']['message'] .= Trad::strBuild(
                                'Le fichier @1@ n\'a pas été exporté.',
                                $file
                            );
                        }
                    }
                } else {
                    $return['data']['message'] .= Trad::strBuild(
                        "Le fichier @1@ pour l'export n'est pas au format json.",
                        $file
                    );
                }
            } else {
                $return['data']['message'] .= Trad::strBuild(
                    "Le fichier @1@ pour l'export est introuvable.",
                    $file
                );
            }
        }

        return $return;
    }
}
