<?php
namespace Modules\API\APIInterne\Mail\Controller;

use Entity\Model\Docatt;
use Helpers\Log\LogSysteme;
use Modules\API\APIInterne\Mail\Outil\OutilMail;
use PHPMailer\PHPMailer\PHPMailer;
use Modules\GlobalApplication\Repository\DocumentsRattaches;
use Helpers\Session\ParseBase1;
use Webklex\PHPIMAP\Client;
use Webklex\PHPIMAP\ClientManager;
use Webklex\PHPIMAP\Exceptions\ConnectionFailedException;

class StandardController extends AbsMailController
{
    /**
     * mailEnvoi
     *
     * @param  string $ID
     * @param  bool $retryNoTLS
     * @param  \Entity\Model\Paravrac $paravrac
     * @param  string $username
     * @param  string $password
     * @param  string $host
     * @param  int $port
     * @param  array<mixed> $infoMail
     * @param  array<mixed> $parametreOauth2
     * @param  array<mixed> $paramDico
     * @return string
     */
    public function mailEnvoi(string $ID, bool $retryNoTLS, \Entity\Model\Paravrac $paravrac, string $username, string $password, string $host, int $port, array $infoMail, array $parametreOauth2, array $paramDico) : string
    {
        $docAtt = new Docatt($this->pdo);
        $message = $docAtt->find([
            'NO_DA' => 'MAIL_SUIVI',
            'COD_ENR' => $paramDico['ALPHA1'],
            'NO_ORDRE' => $infoMail['FIC_MSG_NO']
        ]);
        
        $bodyFile = (new ParseBase1())->getRep()->pj.$message['NOM_FIC'];
        $body = file_get_contents($bodyFile, true);
        if ($body === false) {
            $body = '';
            LogSysteme::prefixErrorLog('Failed to open file "'.$bodyFile.'"');
        }
        $body = \Helpers\Outil\StringHelper::utf8Encode($body); // Note : .msg are not encoded in UTF8

        $docAtt = new DocumentsRattaches($this->pdo);

        $pj = $docAtt->selectPJDocAtt($infoMail['FIC_PJ_NO_MIN'], $infoMail['FIC_PJ_NO_MAX'], $paramDico['ALPHA1']);
        $auth = 0;
        $debugLog = 'SERVER NAME : ' . LogSysteme::getServerName() . PHP_EOL;
        $debugLog .=" chemin body : ".(new ParseBase1())->getRep()->pj.$message['NOM_FIC'].PHP_EOL;
        
        /**
         * Recuperation du chemin du fichier de log
         */
        $directoryLog = OutilMail::getDirectoryLog($paramDico['ALPHA2']);
        
        try {
            $mail             = new PHPMailer();
            $mail->IsSMTP();
            $mail->Host       = $host;
            $mail->Port       = $port;
            $mail->Username       = $username;
            if (trim($password) != '') {
                $auth++;
                $mail->Password = $password;
            }
            
            $mail->CharSet = 'UTF-8';
            $mail->SMTPOptions = array('ssl' => array('verify_peer' => false,'verify_peer_name' => false,'allow_self_signed' => true));


            if ($auth) {
                $mail->SMTPAuth   = true;
            }
            
            /**
             * Catch du login sur le log
             */
            $debugLog .=" Login connexion SMTP : ".\Helpers\Outil\StringHelper::utf8Decode($mail->Username).PHP_EOL;

            if (isset($infoMail['EMAIL_FROM']) && $infoMail['EMAIL_FROM']!='') {
                $mail->FromName = $mail->From = explode(';', str_replace(',', ';', $infoMail['EMAIL_FROM']))[0];
                $debugLog .=" From : ". $infoMail['EMAIL_FROM'] .PHP_EOL;
            }
            
            if (isset($infoMail['SUJET']) && trim($infoMail['SUJET'])!='') {
                $mail->Subject = $infoMail['SUJET']; // sujet
                
                $debugLog .=" Subject : ". $infoMail['SUJET'] .PHP_EOL;
            }
            // $mail->AltBody    = "<h1>Merci de mettre la CB</h1>"; //Body au format texte
            $mail->SMTPDebug = 10;
            $mail->Debugoutput = function ($str, $level) use (&$debugLog) {
                if (strpos($str, 'CLIENT -> SERVER') === false) {
                    if (trim($str) != '') {
                        $debugLog .=date('Y-m-d H:i:s').' '. $str .PHP_EOL;
                    }
                }
            };
    
            if ($retryNoTLS == false) {
                $mail->SMTPSecure = 'tls';
            }
            
            // $mail->WordWrap   = 50; // nombre de caractères pour le retour à la ligne automatique
            if (!empty(trim($body))) {
                $mail->MsgHTML(nl2br($body));
                $debugLog .=" MsgHTML : ".$body.PHP_EOL;
            } else {
                $mail->MsgHTML(' ');
                $debugLog .=" MsgHTML : ''".PHP_EOL;
            }
            
            
            // pièce jointe
            foreach ($pj as $pjAttachement) {
                $mail->AddAttachment((new ParseBase1())->getRep()->pj.$pjAttachement['NOM_FIC'], $pjAttachement['NOM_ORI'] ? $pjAttachement['NOM_ORI'] : $pjAttachement['NOM_FIC']);
            }

            $logPieceJointe = var_export($pj, true);
            $debugLog .=" PIECES JOINTE : ".$logPieceJointe.PHP_EOL;
    
            
            if ($infoMail['EMAIL_REPLY_TO']??false) {
                if (strpos($infoMail['EMAIL_REPLY_TO'], ',') || strpos($infoMail['EMAIL_REPLY_TO'], ';')) {
                    $mailExplode = explode(';', str_replace(',', ';', $infoMail['EMAIL_REPLY_TO']));
    
                  
                    foreach ($mailExplode as $mailToExplode) {
                        $mail->AddReplyTo(trim($mailToExplode));
                        $debugLog .=" Destinataire reply to : ".trim($mailToExplode).PHP_EOL;
                    }
                } else {
                    $mail->AddReplyTo($infoMail['EMAIL_REPLY_TO']);
                    $mail->Sender = $infoMail['EMAIL_REPLY_TO'];
                    $debugLog .=" Destinataire reply to : ".trim($infoMail['EMAIL_REPLY_TO']).PHP_EOL;
                }
            }
            
            if ($infoMail['EMAIL_TO']??false) {
                if (strpos($infoMail['EMAIL_TO'], ',') || strpos($infoMail['EMAIL_TO'], ';')) {
                    $mailExplode = explode(';', str_replace(',', ';', $infoMail['EMAIL_TO']));
    
                  
                    foreach ($mailExplode as $mailToExplode) {
                        $mail->AddAddress(trim($mailToExplode));
                        $debugLog .=" Destinataire : ".trim($mailToExplode).PHP_EOL;
                    }
                } else {
                    $mail->AddAddress($infoMail['EMAIL_TO']);
                    $debugLog .=" Destinataire : ".trim($infoMail['EMAIL_TO']).PHP_EOL;
                }
            }
            
            // Copie cachée
            if ($infoMail['EMAIL_CC']??false) {
                if (strpos($infoMail['EMAIL_CC'], ',') || strpos($infoMail['EMAIL_CC'], ';')) {
                    $mailExplode = explode(';', str_replace(',', ';', $infoMail['EMAIL_CC']));
                  
                    foreach ($mailExplode as $mailToExplode) {
                        $mail->addCC(trim($mailToExplode));
                        $debugLog .=" Destinataire CC : ".trim($mailToExplode).PHP_EOL;
                    }
                } else {
                    $mail->addCC($infoMail['EMAIL_CC']);
                    $debugLog .=" Destinataire CC : ".trim($infoMail['EMAIL_CC']).PHP_EOL;
                }
            }

            
            if ($infoMail['EMAIL_BCC']??false) {
                if (strpos($infoMail['EMAIL_BCC'], ',') || strpos($infoMail['EMAIL_BCC'], ';')) {
                    $mailExplode = explode(';', str_replace(',', ';', $infoMail['EMAIL_BCC']));
                  
                    foreach ($mailExplode as $mailToExplode) {
                        $debugLog .=" Destinataire BCC : ".trim($mailToExplode).PHP_EOL;
                        $mail->AddBCC(trim($mailToExplode));
                    }
                } else {
                    $mail->AddBCC($infoMail['EMAIL_BCC']);
                    $debugLog .=" Destinataire BCC : ".trim($infoMail['EMAIL_BCC']).PHP_EOL;
                }
            }
            
            $mail->IsHTML(true); // envoyer au format html, passer a false si en mode texte
    
            if (!$mail->Send()) {
                if ($retryNoTLS == true) {
                    file_put_contents($directoryLog, $debugLog.PHP_EOL.$mail->ErrorInfo.PHP_EOL.'ERRORLEVEL: 1', FILE_APPEND);
                } else {
                    file_put_contents($directoryLog, $debugLog.PHP_EOL.$mail->ErrorInfo.PHP_EOL.'RETRY_WITH_NOTLS', FILE_APPEND);
                }

                if ($retryNoTLS == false) {
                    return $this->mailEnvoi($ID, true, $paravrac, $username, $password, $host, $port, $infoMail, $parametreOauth2, $paramDico);
                }

                if (isset($_SESSION['contextMailAsync']) &&
                    $_SESSION['contextMailAsync'] == true
                ) {
                    return 'Sync';
                }
                
                return "Statut|NOOK|";
            } else {
                file_put_contents($directoryLog, $debugLog.PHP_EOL.'ERRORLEVEL: 0', FILE_APPEND);

                if (isset($_SESSION['contextMailAsync']) &&
                    $_SESSION['contextMailAsync'] == true
                ) {
                    return 'Sync';
                }

                return "Statut|OK|";
            }
        } catch (\Exception $e) {
            if ($retryNoTLS == true) {
                file_put_contents($directoryLog, $debugLog.PHP_EOL.$mail->ErrorInfo.PHP_EOL.$e->getMessage().PHP_EOL.'ERRORLEVEL: 1', FILE_APPEND);
            } else {
                file_put_contents($directoryLog, $debugLog.PHP_EOL.$mail->ErrorInfo.PHP_EOL.$e->getMessage().PHP_EOL.'RETRY_WITH_NOTLS', FILE_APPEND);
            }

            if ($retryNoTLS == false) {
                return $this->mailEnvoi($ID, true, $paravrac, $username, $password, $host, $port, $infoMail, $parametreOauth2, $paramDico);
            }

            if (isset($_SESSION['contextMailAsync']) &&
                $_SESSION['contextMailAsync'] == true
            ) {
                return 'Sync';
            }

            return "Statut|NOOK|";
        }
    }

    public function testEmailReadConnection(object $config) :void
    {
        if (!extension_loaded('imap')) {
            throw new \Exception('Missing php extention imap');
        }
        $imapConf = $config->imap_config;
        $mbox = imap_open(
            '{'
            . $imapConf['host']
            . (isset($imapConf['port']) ?
                ':'.$imapConf['port'] : ''
            )
            . ($imapConf['encryption'] == 'ssl' ?
                '/imap/ssl/novalidate-cert' : ''
            )
            .'}',
            $imapConf['username'],
            $imapConf['password']
        );
        
        if ($mbox === false) {
            $error = imap_errors();
            throw new \Exception('imap_open failed : '. ($error === false ? 'no error' : var_export($error, true) ));
        }
        
        imap_close($mbox);

        
        // (new ClientManager());// Required by Clients
        // $client = (new Client($config->imap_config));
        // try {
        //     $client->connect();
        // } catch (ConnectionFailedException $e) {
        //     // Bug (dossier 40513) after a failed connection the client try
        //     // to logout and get stuck trying to read a response
        //     /** @phpstan-ignore-next-line */
        //     $client->getConnection()->stream = null;
        //     throw $e;
        // }
    }
}
