<?php

namespace Shm\ShmRPC\ShmRPCCodeGen\CodeGenPhp;

use Shm\Shm;

class CreateRequestClass
{
    private string $namespace = '';
    private string $dirFiles = '';
    private string $className = '';
    private string $methodName = '';

    public function __construct(string $namespace, string $dirFiles, string $className, string $methodName)
    {
        $this->namespace = $namespace;
        $this->dirFiles = $dirFiles;
        $this->methodName = $methodName;

        //Создаем папку если не существует
        if (!is_dir($this->dirFiles)) {
            mkdir($this->dirFiles, 0777, true);
        }

        $this->className = $className;
    }

    public function create(array $params)
    {

        $class = new \Nette\PhpGenerator\ClassType($this->className);



        $extensionsStructure = $params['type']->extensionsStructure();

        $extensionsCollection = array_keys($extensionsStructure);




        if (isset($params['args'])) {

            $argsClassName = $this->className . 'Args';

            $createClassByStructure = new CreateClassByStructure($this->namespace, $this->dirFiles, $argsClassName);
            $createClassByStructure->create($params['args']);

            $class->addProperty('args')->setType($argsClassName);

            $method = $class->addMethod('createArgs');
            $method->setReturnType($argsClassName);
            $method->setStatic();
            $method->setBody('return new ' . $argsClassName . '();');

            $method = $class->addMethod('setArgs');
            $method->addParameter('args')->setType($argsClassName);
            $method->setReturnType('self');
            $method->setBody('$this->args = $args; return $this;');
        }

        if (count($extensionsCollection) > 0) {

            $class->addProperty('extensions')->setType('array')->setValue([]);


            foreach ($extensionsCollection as $extension) {

                $method = $class->addMethod('extensions' . ucfirst($extension));
                $method->setReturnType('self');
                $method->setBody('$this->extensions[] = "' . $extension . '"; return $this;');

                // $class->addProperty($extension)->setType($extension);
            }
        }

        $responseClassName = ucfirst($this->methodName) . 'Response';
        $createClassResponse = new CreateClassResponse($this->namespace, $this->dirFiles, $responseClassName);

        $responseStructure = [
            'success' => Shm::boolean(),
            'result' => $params['type'],
            'error' => Shm::string(),
            'method' => Shm::string(),
        ];

        if (count($extensionsCollection) > 0) {
            $extensionStructure = [];
            foreach ($extensionsCollection as $extension) {
                $extensionStructure[$extension] = Shm::arrayOf(Shm::mixed());
            }
            $responseStructure['extensions'] = Shm::structure($extensionStructure);
        }




        $createClassResponse->create(Shm::structure($responseStructure));


        $method = $class->addMethod('send');

        $sendBody = [
            '$requestParams = [];',
        ];

        if (isset($params['args'])) {
            $sendBody[] = '$requestParams["params"] =  isset($this->args) ? $this->args->data() : [];';
        } else {
            $sendBody[] = '$requestParams["params"] = [];';
        }

        $sendBody[] = '$requestParams["method"] = "' . $this->methodName . '";';


        if (count($extensionsCollection) > 0) {
            $sendBody[] = '$requestParams["extensions"] = $this->extensions;';
        } else {
            $sendBody[] = '$requestParams["extensions"] = [];';
        }
        //  $sendBody[] = 'var_dump($requestParams); exit;';
        $sendBody[] = '$result = ApiClient::_sendRequest($requestParams["method"], $requestParams["params"], $requestParams["extensions"]);';
        $sendBody[] = 'return new ' . $responseClassName . '($result);';

        $method->setBody(implode(' ', $sendBody));
        $method->setReturnType($responseClassName);


        $output = "<?php\n\n"; // заголовок файла
        $output .= "namespace " . $this->namespace . ";\n";

        $output .= 'use App\ApiClient\ApiClient;' . "\n\n";
        $output .= $class . "\n\n"; // собираем все классы

        $filePath = $this->dirFiles . $this->className . '.php';
        file_put_contents($filePath, $output);
    }
}