<?php 

error_reporting(E_ALL);
ini_set('display_errors', E_ALL);

$varname = time();

list(${"{$varname}_script"}, ${"{$varname}_path"}, ${"{$varname}_vendor_path"}) = $argv;

${"{$varname}_vendor_path"} = str_replace('--vendor=', '', ${"{$varname}_vendor_path"});

if(empty(${"{$varname}_vendor_path"})) {
  ${"{$varname}_vendor_path"} = 'vendor/autoload.php';
}

if (file_exists(${"{$varname}_vendor_path"})) {
  require ${"{$varname}_vendor_path"};
}

${"{$varname}_path"} = ${"{$varname}_path"} ?? '.';

${"{$varname}_rii"} = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(${"{$varname}_path"}));

${"{$varname}_files"} = [];
${"{$varname}_classes"} = [];
${"{$varname}_tmp_dir"} = dirname(__FILE__) . '/tmp';

if(!file_exists(${"{$varname}_tmp_dir"})) {
  mkdir(${"{$varname}_tmp_dir"}, 0755, true);
}

${"{$varname}_errors"} = 0;

foreach(${"{$varname}_rii"} as ${"{$varname}_file"}) {
  if(!${"{$varname}_file"}->isDir()) {
    ${"{$varname}_files"}[] = ${"{$varname}_file"}->getPathname();
    ${"{$varname}_contents"} = file_get_contents(${"{$varname}_file"}->getPathname());
    preg_match('/namespace ([^;]+)/i', ${"{$varname}_contents"}, ${"{$varname}_matches"});
    ${"{$varname}_namespace"} = ${"{$varname}_matches"}[1]??'';
    ${"{$varname}_classname"} = ${"{$varname}_namespace"} . '\\' . str_replace(['.php'], '', basename(${"{$varname}_file"}->getPathname()));
    ${"{$varname}_rc"} = new ReflectionClass(${"{$varname}_classname"});
    ${"{$varname}_methods"} = ${"{$varname}_rc"}->getMethods( ReflectionMethod::IS_STATIC|ReflectionMethod::IS_PUBLIC|ReflectionMethod::IS_PROTECTED|ReflectionMethod::IS_PRIVATE|ReflectionMethod::IS_ABSTRACT|ReflectionMethod::IS_FINAL);
    foreach(${"{$varname}_methods"} as ${"{$varname}_rm"}) {
      ${"{$varname}_tests"} = [];
      preg_match_all('/\@test[\s]+(.*)/', ${"{$varname}_rm"}->getDocComment(), ${"{$varname}__matches"});
      if(isset(${"{$varname}__matches"}[1])) {
        foreach(${"{$varname}__matches"}[1] as ${"{$varname}__test_key"} => ${"{$varname}_test"}) {
          ${"{$varname}_tmp_name"} = md5(microtime());
          ${"{$varname}_tmp"} = "{${"{$varname}_tmp_dir"}}/test-{${"{$varname}_tmp_name"}}.php";          
          ${"{$varname}_test"} = str_replace(['{class}', '{method}'], [${"{$varname}_classname"}, ${"{$varname}_rm"}->getName()], ${"{$varname}_test"});
          file_put_contents(${"{$varname}_tmp"}, "<?php {${"{$varname}_test"}};");
          ob_start();
          ${"{$varname}_result"} = require ${"{$varname}_tmp"};
          ob_end_clean();
          echo "File: {${"{$varname}_rm"}->getFileName()}\n";
          echo "Line: {${"{$varname}_rm"}->getEndLine()}\n";
          echo "Source: {${"{$varname}_test"}}\n";
          echo "Return: "; var_dump(${"{$varname}_result"});
          echo "Status: " . (${"{$varname}_result"} ? 'Success' : 'Failed');
          echo "\n\n";
          unlink(${"{$varname}_tmp"});
          if(!${"{$varname}_result"}) {
            ${"{$varname}_errors"}++;
          }
        }
      }
    }
  }
}

if(${"{$varname}_errors"}) {
  exit("\033[31m There is something wrong! Try review your code.\033[0m\n");
}
exit("\033[92m Congratulations! All tests are passed.\033[0m\n");