<?php declare(strict_types=1);

namespace Helpers\Scheduler;

use Entity\Model\TploOperations;
use Exception;
use Helpers\Log\LogSysteme;
use Helpers\Outil\Date;
use Helpers\Outil\Sql;
use Helpers\User\User;
use Psr\Container\ContainerInterface;

/**
 * Summary of Scheduler
 * Permet de planifier ou supprimer des évènements
 *
 * La liste des évènements doit être présente dans
 * API\Batch
 */
class Scheduler
{

    public function __construct(
        private TploOperations $tploOperations,
    ) {
    }

    /**
     * Summary of createBatchName
     * @param string $batchName
     * @throws \Exception
     * @return string
     */
    private function createBatchName(
        string $batchName,
    ): string {
        $batchName = "Batch:{$batchName}";
        if (strlen($batchName) > 100) {
            throw new Exception("La longeur de createBatchName ne peut pas dépasser 100 caractères. batchname: {$batchName}");
        }
        return $batchName;
    }

    /**
     * Summary of createStringParam
     * @param array<mixed> $params
     * @throws \Exception
     * @return string
     */
    private function createStringParam(array $params): string
    {
        // Important de laisser tel quel au vue du traitement actuel du batch.php
        $stringParam = '0 0 ';
        foreach ($params as $key => $value) {
            $stringParam .= "--{$key}={$value}";
        }
        if (strlen($stringParam) > 3000) {
            throw new Exception("La longeur de createStringParam ne peut pas dépasser 3000 caractères. stringparam: {$stringParam}");
        }
        return $stringParam;
    }

    /**
     * Summary of verifyClass
     * @param string $dirName
     * @param string $className
     * @throws \Exception
     * @return void
     */
    private function verifyClass(string $dirName, string $className): void
    {
        if (!class_exists("API\\Batch\\{$dirName}\\{$className}")) {
            throw new Exception("La classe {$className} pour le module {$dirName} n'existe pas: 'API\\Batch\\{$dirName}\\{$className}'");
        }
    }

    /**
     * Summary of verifyMethod
     * @param string $dirName
     * @param string $className
     * @param string $methodName
     * @throws \Exception
     * @return void
     */
    private function verifyMethod(string $dirName, string $className, string $methodName): void
    {
        if (!method_exists("API\\Batch\\{$dirName}\\{$className}", $methodName)) {
            throw new Exception("La méthode {$methodName} pour la classe {$className} n'existe pas: 'API\\Batch\\{$dirName}\\{$className}'");
        }
    }

    /**
     * Summary of verifyAndCreateBatchName
     * @param string $batchName
     * @return string
     */
    private function verifyAndCreateBatchName(string $batchName): string
    {
        [$dirName, $className, $methodName] = explode('.', $batchName, 3);
        $this->verifyClass($dirName, $className);
        $this->verifyMethod($dirName, $className, $methodName);
        return $this->createBatchName($batchName);
    }

    /**
     * Summary of create
     * @param string $batchName format '{module}.{className}.{methodName}'
     * @param array<mixed> $params format [$key => value]
     * @param string $date format YYYMMDD
     * @param string $time format HHIISS
     * @return bool
     */
    public function create(
        string $batchName,
        array $params,
        string $date,
        string $time,
    ): bool {
        $batchName = $this->verifyAndCreateBatchName($batchName);

        try {
            $stringParam = $this->createStringParam($params);

            $time = str_replace(':', '', $time);
            $guid = Sql::guidGenerate();

            $values = [
                'TPLO_ID_OPERATION' => $guid,
                'TPLO_TYPE_OPERATION' => 'P',
                'TPLO_ID_TACHE' => '',
                'TPLO_CODE_OPERATION' => $batchName,
                'TPLO_DTETIME_EXEC' => "{$date}{$time}",
                'TPLO_CODE_USER' => User::getUser()->getCodeUser(),
                'TPLO_TRT_PARAM' => $stringParam,
                'TPLO_STATUT' => 'A',
                'TPLO_LECTURELOG' => Sql::boolSql2(false),
                'TPLO_FIC_LOG' => ''
            ];

            $success = $this->tploOperations->insert($values);

            if (!$success) {
                $stringValues = @print_r($values, true);
                LogSysteme::prefixErrorLog("Un problème est survenu dans l'enregistrement d'un évènement : {$stringValues}");
            }

            return true;
        } catch (Exception $e) {
            LogSysteme::prefixErrorLog($e->getMessage());
        }
        return false;
    }


    /**
     * Summary of delete
     * @param string $batchName format '{module}.{className}.{methodName}'
     * @param array<mixed> $params format [$key => value]
     * @return bool
     */
    public function delete(
        string $batchName,
        array $params
    ): bool {
        $batchName = $this->verifyAndCreateBatchName($batchName);

        try {
            $stringParam = $this->createStringParam($params);

            $this->tploOperations->delete([
                'TPLO_TYPE_OPERATION' => 'P',
                'TPLO_CODE_OPERATION' => $batchName,
                'TPLO_TRT_PARAM' => $stringParam,
                'TPLO_STATUT' => 'A',
                'TPLO_LECTURELOG' => Sql::boolSql2(false),
            ]);

            return true;
        } catch (Exception $e) {
            LogSysteme::prefixErrorLog($e->getMessage());
        }
        return false;
    }
}
