<?php

namespace Tests\Utils;

class ClassMethodScanner
{
    // 递归获取指定目录下所有 PHP 文件
    private function getPhpFiles($dir)
    {
        $phpFiles = [];
        $files = scandir($dir);

        foreach ($files as $file) {
            if ($file === '.' || $file === '..') {
                continue;
            }

            $filePath = $dir . DIRECTORY_SEPARATOR . $file;

            // 如果是目录,则递归调用
            if (is_dir($filePath)) {
                $phpFiles = array_merge($phpFiles, $this->getPhpFiles($filePath));
            } elseif (pathinfo($filePath, PATHINFO_EXTENSION) === 'php') {
                $phpFiles[] = $filePath;
            }
        }

        return $phpFiles;
    }

    // 获取指定目录下的所有文件的 URL
    public function getClassesAndMethods($dir)
    {
        $files = $this->getPhpFiles($dir);
        $classesAndMethodsUrl = [];

        foreach ($files as $file) {
            $fileCont = file_get_contents($file); // 读取文件内容

            // 匹配 @Apidoc\Url 注解中的 URL
            $pattern = '/@Apidoc\\\\Url\("([^"]+)"\)/'; 
            preg_match_all($pattern, $fileCont, $matches); 

            // 匹配 protected $noNeedLogin 数组中的元素
            preg_match('/protected\s+\$noNeedLogin\s*=\s*\[(.*?)\];/', $fileCont, $noNeedLogin);

            // 处理 noNeedLogin 数组
            $noNeedLoginElements = [];
            if (!empty($noNeedLogin[1])) {
                preg_match_all("/'([^']+)'/", $noNeedLogin[1], $noNeedLoginElements);
                $noNeedLoginElements = $noNeedLoginElements[1];  // 获取到数组中的元素
            }

            // 将匹配到的 URL 添加到结果数组中
            if (!empty($matches[1])) {
                foreach ($matches[1] as $url) {
                    // 检查 URL 是否不包含在 noNeedLogin 数组中
                    if(!$this->stringContainsArray($url, $noNeedLoginElements)) {
                        $classesAndMethodsUrl[] = $url;
                    }
                }
            }
        }

        return $classesAndMethodsUrl;
    }

    // 检查字符串是否包含数组中的元素
    private function stringContainsArray($string, $array)
    {
        return !empty(array_filter($array, function($substring) use ($string) {
            return strpos($string, $substring) !== false;
        }));
    }
}