<?php

namespace xmvc\doc\phpdoc;

use xmvc\MVC;
use xmvc\Dump;
use xmvc\Cache;
use xmvc\Encoder;
use ReflectionClass;
use ReflectionFunction;
use phpDocumentor\Reflection\DocBlockFactory;

class Index
{
    protected $type = '';
    public function __construct()
    {
        ;
    }

    /**
     * 标题
     */
    public function title(string $type): string
    {
        if ($type == 'xmvc') {
            return 'XMVC 开发文档';
        } elseif ($type == 'project') {
            return strtoupper(PROJECT) . ' 开发文档';
        } else {
            error(lg('不支持的类型'));
        }
    }

    /**
     * 源代码的目录数组
     * @return string[]
     */
    public function codeDirArr(string $type): array
    {
        if ($type == 'xmvc') {
            return cfgDirToTrueDir(cfg('mvcPhpDocDirs'));
        } elseif ($type == 'project') {
            return cfgDirToTrueDir(cfg('projectPhpDocDirs'));
        } else {
            error(lg('不支持的类型'));
        }
    }

    /**
     * 分析结果的目录
     */
    public function parseDir(string $type): string
    {
        if ($type == 'xmvc') {
            return DIR_MVC . '/doc/phpdoc/parse';
        } elseif ($type == 'project') {
            return ROOT . '/doc/parse';
        } else {
            error(lg('不支持的类型'));
        }
    }


    /** 参数数组转字符串 */
    public function getParamsString(array|null $parameters)
    {
        $result = '';
        if (empty($parameters)) {
            return '';
        }
        foreach ($parameters as $v) {
            if ($result != '') {
                $result .= ', ';
            }
            if ($v['type']) {
                if ($v['isBuiltin']) {
                    $result .= '<span class="param-type">' . $v['type'] . '</span> ';
                } else {
                    $result .= '<span class="param-type-not-builtin">' . $v['type'] . '</span> ';
                }
            }
            if ($v['isVariadic']) {
                $result .= '...';
            }
            $result .= '<span class="param-var">' . '$' . $v['name'] . '</span> ';
            if ($v['default'] != '<phpdoc_null>') {
                if ($v['default'] === '') {
                    $v['default'] = "''";
                } elseif ($v['default'] === null) {
                    $v['default'] = "NULL";
                } elseif (is_string($v['default'])) {
                    $v['default'] = "'" . $v['default']  . "'";
                } elseif (is_bool($v['default'])) {
                    $v['default'] =  $v['default'] ? 'true' : 'false';
                } elseif (is_numeric($v['default'])) {
                    $v['default'] = $v['default'];
                } elseif (is_array($v['default'])) {
                    $v['default'] = '[]';
                } else {
                    dd($v, $parameters);
                }
                $result .= ' = ' . '<span class="param-default">' . $v['default'] . '</span> ';
            }
        }
        return $result;
    }

    /** 处理 Tags 内容
     */
    public function parseTags(array $item, array $filterArr = []): array
    {
        $result = [];
        if (isset($item['docBlock']['tags'])) {
            foreach ($item['docBlock']['tags'] as $tag) {
                $text = trim($tag['description']);
                if ('param' == $tag['name'] && (empty($filterArr) || in_array($tag['name'], $filterArr))) { // 参数
                    $paramType = '';
                    // 参数名称
                    if (preg_match('/\$([a-zA-Z\_0-9]+)(?!\w)/', $text, $m)) {
                        foreach ($item['parameters'] as $paramItem) {
                            if ($paramItem['name'] == $m[1]) {
                                if (!$paramItem['isBuiltin']) {
                                    $paramType = '<span class="param-type-not-builtin">' . $paramItem['type'] . '</span>';
                                }
                                break;
                            }
                        }
                    }
                    // 类型 和 描述
                    $spacePos = mb_strpos($text, ' ');
                    if ($spacePos > 0) {
                        if ($paramType == '') {
                            $paramType = '<span class="param-type">' . mb_substr($text, 0, $spacePos) . '</span>';
                        }
                        $text = $paramType . mb_substr($text, $spacePos);
                    }
                    // 变量
                    $text =  preg_replace(
                        '/(\$[a-zA-Z\_0-9]+)(?!\w)/',
                        '<span class="param-var">$1</span>',
                        $text
                    );
                    $result[] .= '<span class="param-fag">@param</span> ' . $text . '';
                } elseif ('return' == $tag['name'] && (empty($filterArr) || in_array($tag['name'], $filterArr))) { // 返回值
                    // 类型
                    $returnType = '';
                    $returnRemark = '';
                    $spacePos = mb_strpos($text, ' ');
                    if ($spacePos === false) {
                        $returnType = $text;
                    } else {
                        $returnType = mb_substr($text, 0, $spacePos);
                        $returnRemark = mb_substr($text, $spacePos);
                    }
                    if (isset($item['returnType']) && $item['returnType'] && $item['returnType'] != 'void') {
                        $returnType = $item['returnType'];
                    }
                    if ($returnType == '') {
                        $returnType = 'void';
                    }
                    if ($item['returnTypeIsBuiltin']) {
                        $returnType = '<span class="param-type">' . $returnType . '</span>';
                    } else {
                        $returnType = '<span class="param-type-not-builtin">' . $returnType . '</span>';
                    }
                    $result[] .= '<span class="param-fag">@return</span> ' . $returnType . ' ' . $returnRemark;
                } elseif ('example' == $tag['name'] && (empty($filterArr) || in_array($tag['name'], $filterArr))) { // 示例
                    $pattern = '/```php\s*(.*?)\s*```/s';
                    if (preg_match($pattern, $text, $m)) {
                        //$text = Dump::phpCodeColor($m[1]);
                        //$text = '<pre class="phpcode">' . $text . '</pre>';
                        $text = '<div class="codeEditor-example"><textarea id="codeEditor-example">' . $m[1] . '</textarea></div>';
                        $text = '<div class="tag-example"><label class="param-fag">@example ↓</label> ' . $text . '</div>';
                    } else {
                        $text = '<div class="tag-example"><label class="param-fag">@example →</label> ' . $text . '</div>';
                    }
                    $result[] .= $text;
                } elseif ('link' == $tag['name'] && (empty($filterArr) || in_array($tag['name'], $filterArr))) { // 参考
                    $spacePos = mb_strpos($text, ' ') ?: mb_strlen($text);
                    $url = mb_substr($text, 0, $spacePos);
                    if (substr($url, 0, 5) === 'HOST/') {
                        $url = HOST . '/' . substr($text, 5);
                    }
                    $urlRemark = $spacePos == mb_strlen($text) ? '' : mb_substr($text, $spacePos);
                    $result[] .= '<span class="param-fag">@link</span> ' . $urlRemark . ' <a href="' . $url . '" class="tag-link" target="_blank">' . $url . '</a>';
                } elseif ('see' == $tag['name'] && (empty($filterArr) || in_array($tag['name'], $filterArr))) { // 参考
                    $spacePos = mb_strpos($text, ' ') ?: mb_strlen($text);
                    $formatText = mb_substr($text, 0, $spacePos);
                    $urlRemark = $spacePos == mb_strlen($text) ? '' : mb_substr($text, $spacePos);
                    if (strtolower(substr($formatText, 0, 4)) == 'http') {
                        $url = $formatText;
                        $text = ' <a href="' . $url . '" class="tag-see">' . $url . '</a>';
                    } elseif (strpos($text, '()') !== false) {
                        if (preg_match('/^\\\\[a-zA-Z_0-9]+\(\)/', $formatText, $m)) {
                            // 如果是 \join() 没有指定类去前面的 \
                            $formatText = substr($formatText, 1);
                        }
                        $opPos = strpos($text, '::');
                        if ($opPos === false) {
                            // 当前类
                            $formatText = CLASS_NAME . '::' . $formatText;
                        }
                        if (strpos($text, '\\') !== 0) {
                            $formatText = '\\' . $text;
                        }
                        $tmp = explode('(', $formatText)[0];
                        list($className, $function) =  explode('::', $tmp);
                        $text = $this->gotoFunction($className, $function, 'tag-see');
                    } elseif (strpos($text, '::') !== false) {
                        list($className, $function) =  explode('::', $text);
                        $text = $this->gotoClass($className, 'tag-see');
                    }
                    $result[] .= '<span class="param-fag">@see</span> ' . $text . ' ' . $urlRemark;
                }
            }
        }
        return $result;
    }

    /** 返回类型字符串
     */
    public function getReturnTypeString(array $item)
    {
        $result = '';
        if (isset($item['returnType']) && $item['returnType'] && $item['returnType'] != 'void') {
            $result = $item['returnType'];
        } elseif (isset($item['docBlock']['tags'])) {
            foreach ($item['docBlock']['tags'] as $tag) {
                if ($tag['name'] == 'return') {
                    $result = $tag['description'];
                    $result = explode(' ', $result)[0];
                }
            }
        } else {
            $result = 'void';
        }
        if ($result == '') {
            $item['returnTypeIsBuiltin'] = true;
            $result = 'void';
        }
        if ($item['returnTypeIsBuiltin']) {
            $result = '<span class="param-type">' . $result . '</span>';
        } else {
            $result = '<span class="param-type-not-builtin">' . $result . '</span>';
        }
        return $result;
    }

    public function parseRemark($previousLines)
    {
        $previousLines = trim($previousLines);
        $strArr = explode("\n", $previousLines);
        $previousLines = [];
        foreach ($strArr as $i => $str) {
            $str = trim($str, '/* ');
            if ($str) {
                /*
                // 替换 - 与 - 之间的空格
                while (preg_match('/(-)\s+(-)/', $str)) {
                    $str = preg_replace('/(-)\s+(-)/', '--', $str);
                }
                // 将 - 替换成空格
                $str = preg_replace_callback('/^(-+)/', function ($m) {
                    return str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;', strlen($m[0]));
                }, $str);
                // 将 // 标记为注释
                $str = preg_replace('/\/\/(.*)/', '<span class="func-line-remark">//$1</span>', $str);
                */
                $previousLines[] = htmlentities(trim($str, '/* '));
            }
        }
        $title = array_shift($previousLines) ?: '';
        $remark = implode('<br >', $previousLines);
        return ['title' => $title, 'remark' => $remark];
    }


    /**
     * 构建节点网址
     */
    public function itemUrl(array $item, string $action = 'doc')
    {
        return url('xmvc/doc/phpdoc/index-' . $action, [
            'type' => $this->type,
            'function' => !isset($item['namespace']) ? $item['name'] : '',
            'parseFile' => $item['parseFile']
        ]);
    }

    public function gotoClass(string $className, $cssClass = '')
    {
        $cssClass = $cssClass ?: 'goto';
        $parseDir = $this->parseDir($this->type);
        $parseFile = $parseDir . '/' . str_replace('\\', '_', ltrim($className, '\\')) . '.php';
        $url = $this->itemUrl([
            'namespace' => '',
            'parseFile' => Encoder::encode($parseFile)
        ], 'doc');
        return '<a href="' . $url . '" class="' . $cssClass . '">' . $className . '</a>';
    }

    public function gotoFunction(string $className, string $function, $cssClass = '')
    {
        $cssClass = $cssClass ?: 'goto';
        $parseDir = $this->parseDir($this->type);
        $parseFile = $parseDir . '/' . str_replace('\\', '_', ltrim($className, '\\')) . '.php';
        $url = $this->itemUrl([
            'name' => $function,
            'parseFile' => Encoder::encode($parseFile)
        ], 'func');
        return '<a href="' . $url . '" class="' . $cssClass . '">' . $className . '::' . $function . ' ()' . '</a>';
    }

    /**
     * index
     */
    public function index(string $type)
    {
        $this->type = $type;
        require(__DIR__ . '/' . __FUNCTION__ . '.tpl.php');
        exit();
    }

    /**
     * 文档页
     */
    public function doc(string $type, string $function, string $parseFile)
    {
        $this->type = $type;
        require(__DIR__ . '/' . __FUNCTION__ . '.tpl.php');
        exit();
    }

    /**
     * 函数页
     */
    public function func(string $type, string $function, string $parseFile)
    {
        $this->type = $type;
        require(__DIR__ . '/' . __FUNCTION__ . '.tpl.php');
        exit();
    }

    /**
     * 概述页
     */
    public function overview()
    {
        require(__DIR__ . '/' . __FUNCTION__ . '.tpl.php');
        exit();
    }

    /**
     * 元数据页
     */
    public function metadata()
    {
        require(__DIR__ . '/' . __FUNCTION__ . '.tpl.php');
        exit();
    }

    /**
     * 生成开发文档
     */
    public function create(string $type)
    {
        $this->type = $type;
        require(__DIR__ . '/' . __FUNCTION__ . '.php');
        MVC::alertExit($this->title($type) . ' 生成完成');
    }

    /**
     * 清空开发文档
     */
    public function clear(string $type)
    {
        $this->type = $type;
        $cacheDir = $this->parseDir($type);
        $cacheFile = new Cache();
        $cacheFile->setCacheFileAbsDir($cacheDir);
        $cacheFile->deleteAllCacheFile(false);
        MVC::alertExit($this->title($type) . ' 清空完成');
    }

    public function parsePhpDoc(string $filename): array|null
    {
        $result = [];

        // 创建一个 DocBlock 工厂
        $factory = DocBlockFactory::createInstance();

        // 读取文件内容
        $fileContent = file_get_contents($filename);

        if (preg_match('/namespace\s+([a-zA-Z0-9_\\\\]+)\s*;/', $fileContent, $m)) {
            $namespace = $m[1];
        } else {
            $namespace = '';
        }

        // 判断是类文件、接口文件还是函数文件
        if (preg_match('/class\s+([a-zA-Z0-9_]+)/', $fileContent, $matches)) {
            // 是类文件
            $className = $namespace . '\\' . $matches[1];
            $classInfo = [
                'codefile' => $filename,
                'type' => 'class',
                'name' => $className,
                'namespace' => $namespace,
                'abstract' => false,
                'extends' => [],
                'methods' => [],
                'properties' => [],
            ];

            // 使用反射 API 获取类注释
            $reflector = new ReflectionClass($className);
            $docComment = $reflector->getDocComment();

            $classInfo['abstract'] = $reflector->isAbstract();

            // 获取类的继承关系
            if ($parentClass = $reflector->getParentClass()) {
                $classInfo['extends'] = $parentClass->getName();
            }

            if ($docComment !== false) {
                $docBlock = $factory->create($docComment);
                // 将类注释信息加入结果数组
                $classInfo['docBlock'] = [
                    'summary' => $docBlock->getSummary(),
                    'tags' => [],
                ];
                // 添加类注释中的标签信息到结果数组
                foreach ($docBlock->getTags() as $tag) {
                    $classInfo['docBlock']['tags'][] = [
                        'name' => $tag->getName(),
                        'description' => (string) $tag,
                    ];
                }
            }

            // 遍历类的方法
            foreach ($reflector->getMethods() as $method) {
                $methodInfo = [
                    'name' => $method->getName(),
                    'visibility' => $this->getVisibility($method),
                    'abstract' => $method->isAbstract(),
                    'parameters' => [],
                    'returnType' => '',
                    'isStatic' => $method->isStatic(), // 是否为静态方法属性
                    'startLine' => $method->getStartLine(), // 方法起始行号
                    'endLine' => $method->getEndLine(), // 方法结束行号
                    'docBlockStartLine' => null,  // 注释起始行
                    'docBlockEndLine' => null,    // 注释结束行
                ];

                // 获取方法的参数信息（名称及类型）
                $isBuiltin = false;
                foreach ($method->getParameters() as $parameter) {
                    $parameterType = $parameter->getType();
                    // 处理参数类型为联合类型的情况
                    if ($parameterType instanceof \ReflectionUnionType) {
                        $isBuiltin = true;
                        $parameterTypeName = implode('|', array_map(function ($type) use ($isBuiltin) {
                            if (!$type->isBuiltin()) {
                                $isBuiltin = false;
                            }
                            return $type->getName();
                        }, $parameterType->getTypes()));
                    } elseif ($parameterType instanceof \ReflectionNamedType) {
                        // 检查参数类型是否为内置类型
                        if ($parameterType->isBuiltin()) {
                            $isBuiltin = true;
                            $parameterTypeName = (string)$parameterType;
                        } else {
                            $parameterTypeName = $parameterType->getName();
                            if (strpos($parameterTypeName, '\\') !== 0) {
                                $parameterTypeName = '\\' . $parameterTypeName;
                            }
                        }
                    } else {
                        $parameterTypeName = 'mixed';
                    }

                    // 检查是否是可变参数
                    $isVariadic = $parameter->isVariadic();

                    // 添加对默认值的获取
                    $default = '<phpdoc_null>';
                    if ($parameter->isDefaultValueAvailable()) {
                        $default = $parameter->getDefaultValue();
                    }

                    $methodInfo['parameters'][] = [
                        'name' => $parameter->getName(),
                        'type' => $parameterTypeName,
                        'default' => $default,
                        'isVariadic' => $isVariadic, // 是否是可变参数
                        'isBuiltin' => $isBuiltin, // 变量类型是否是系统类型
                    ];
                }


                // 获取方法的返回值类型
                $isBuiltin = false;
                $returnType = $method->getReturnType();
                if ($returnType) {
                    if ($returnType instanceof \ReflectionUnionType) {
                        $isBuiltin = true;
                        $methodInfo['returnType'] = implode('|', array_map(function ($type) use ($isBuiltin) {
                            if (!$type->isBuiltin()) {
                                $isBuiltin = false;
                            }
                            return $type->getName();
                        }, $returnType->getTypes()));
                    } elseif ($returnType instanceof \ReflectionNamedType) {
                        if ($returnType->isBuiltin()) {
                            $isBuiltin = true;
                            $methodInfo['returnType'] = (string)$returnType;
                        } else {
                            $returnTypeName = $returnType->getName();
                            if (strpos($returnTypeName, '\\') !== 0) {
                                if ($returnTypeName == 'self') {
                                    $returnTypeName = '\\' . $className;
                                } else {
                                    $returnTypeName = '\\' . $returnTypeName;
                                }
                            }
                            $methodInfo['returnType'] = $returnTypeName;
                        }
                    } else {
                        $methodInfo['returnType'] = 'mixed';
                    }
                } else {
                    $methodInfo['returnType'] = 'void';
                }
                $methodInfo['returnTypeIsBuiltin'] = $isBuiltin;

                // 获取方法的注释信息
                $docComment = $method->getDocComment();
                // 查找注释的起始行和结束行
                $docCommentLines = explode("\n", $docComment);
                $methodInfo['docBlockStartLine'] = $method->getStartLine() - count($docCommentLines);
                $methodInfo['docBlockEndLine'] = $method->getStartLine() - 1;
                if ($docComment !== false) {
                    $docBlock = $factory->create($docComment);
                    $methodInfo['docBlock'] = [
                        'summary' => $docBlock->getSummary(),
                        'tags' => [],
                    ];
                    // 添加方法注释中的标签信息到结果数组
                    foreach ($docBlock->getTags() as $tag) {
                        $methodInfo['docBlock']['tags'][] = [
                            'name' => $tag->getName(),
                            'description' => (string) $tag,
                        ];
                    }
                }
                $classInfo['methods'][] = $methodInfo;
            }

            // 遍历类的属性
            foreach ($reflector->getProperties() as $property) {
                $propertyType = $property->getType();
                $propertyTypeName = '';
                $isBuiltin = false;

                // 处理参数类型为联合类型的情况
                if ($propertyType instanceof \ReflectionUnionType) {
                    $types = [];
                    $isBuiltin = true;
                    foreach ($propertyType->getTypes() as $type) {
                        if (!$type->isBuiltin()) {
                            $isBuiltin = false;
                        }
                        $types[] = $type->getName();
                    }
                    $propertyTypeName = implode('|', $types);
                } elseif ($propertyType instanceof \ReflectionNamedType) {
                    // 检查参数类型是否为内置类型
                    $isBuiltin = $propertyType->isBuiltin();
                    $propertyTypeName = $propertyType->getName();
                    if (!$isBuiltin && strpos($propertyTypeName, '\\') !== 0) {
                        $propertyTypeName = '\\' . $propertyTypeName;
                    }
                    if ($propertyTypeName == '\\') {
                        $propertyTypeName = '';
                    }
                } else {
                    $propertyTypeName = 'mixed';
                    $isBuiltin = true;
                }
                $propertyInfo = [
                    'name' => $property->getName(),
                    'visibility' => $this->getVisibility($property),
                    'type' => $propertyTypeName,
                    'isBuiltin' => $isBuiltin, //
                ];
                // 获取属性的注释信息
                $docComment = $property->getDocComment();
                if ($docComment !== false) {
                    $docBlock = $factory->create($docComment);
                    $propertyInfo['docBlock'] = [
                        'summary' => $docBlock->getSummary(),
                        'tags' => [],
                    ];
                    // 添加属性注释中的标签信息到结果数组
                    foreach ($docBlock->getTags() as $tag) {
                        $propertyInfo['docBlock']['tags'][] = [
                            'name' => $tag->getName(),
                            'description' => (string) $tag,
                        ];
                    }
                }
                $classInfo['properties'][] = $propertyInfo;
            }

            // 将类信息加入结果数组
            $result = $classInfo;
        } elseif (preg_match('/interface\s+([a-zA-Z0-9_]+)/', $fileContent, $matches)) {
            // 是接口文件
            $interfaceName = $namespace . '\\' . $matches[1];
            $interfaceInfo = [
                'codefile' => $filename,
                'type' => 'interface',
                'name' => $interfaceName,
                'namespace' => $namespace,
                'methods' => [],
            ];

            // 使用反射 API 获取接口注释
            $reflector = new ReflectionClass($interfaceName);
            $docComment = $reflector->getDocComment();

            if ($docComment !== false) {
                $docBlock = $factory->create($docComment);
                // 将接口注释信息加入结果数组
                $interfaceInfo['docBlock'] = [
                    'summary' => $docBlock->getSummary(),
                    'tags' => [],
                ];
                // 添加接口注释中的标签信息到结果数组
                foreach ($docBlock->getTags() as $tag) {
                    $interfaceInfo['docBlock']['tags'][] = [
                        'name' => $tag->getName(),
                        'description' => (string) $tag,
                    ];
                }
            }

            // 遍历接口的方法
            foreach ($reflector->getMethods() as $method) {
                $methodInfo = [
                    'name' => $method->getName(),
                    'visibility' => $this->getVisibility($method),
                    'parameters' => [],
                    'returnType' => '',
                    'isStatic' => $method->isStatic(), // 添加是否为静态方法属性
                    'startLine' => $method->getStartLine(), // 方法起始行号
                    'endLine' => $method->getEndLine(), // 方法结束行号
                    'docBlockStartLine' => null,  // 注释起始行
                    'docBlockEndLine' => null,    // 注释结束行
                ];

                // 获取方法的参数信息（名称及类型）
                $isBuiltin = false;
                foreach ($method->getParameters() as $parameter) {
                    $parameterType = $parameter->getType();
                    // 处理参数类型为联合类型的情况
                    if ($parameterType instanceof \ReflectionUnionType) {
                        $isBuiltin = true;
                        $parameterTypeName = implode('|', array_map(function ($type) use ($isBuiltin) {
                            if (!$type->isBuiltin()) {
                                $isBuiltin = false;
                            }
                            return $type->getName();
                        }, $parameterType->getTypes()));
                    } elseif ($parameterType instanceof \ReflectionNamedType) {
                        // 检查参数类型是否为内置类型
                        if ($parameterType->isBuiltin()) {
                            $isBuiltin = true;
                            $parameterTypeName = (string)$parameterType;
                        } else {
                            $parameterTypeName = $parameterType->getName();
                            if (strpos($parameterTypeName, '\\') !== 0) {
                                $parameterTypeName = '\\' . $parameterTypeName;
                            }
                        }
                    } else {
                        $parameterTypeName = 'mixed';
                    }

                    // 检查是否是可变参数
                    $isVariadic = $parameter->isVariadic();

                    // 添加对默认值的获取
                    $default = '<phpdoc_null>';
                    if ($parameter->isDefaultValueAvailable()) {
                        $default = $parameter->getDefaultValue();
                    }

                    $methodInfo['parameters'][] = [
                        'name' => $parameter->getName(),
                        'type' => $parameterTypeName,
                        'default' => $default,
                        'isVariadic' => $isVariadic,
                        'isBuiltin' => $isBuiltin,
                    ];
                }

                // 获取方法的返回值类型
                $isBuiltin = false;
                $returnType = $method->getReturnType();
                if ($returnType) {
                    if ($returnType instanceof \ReflectionUnionType) {
                        $isBuiltin = true;
                        $methodInfo['returnType'] = implode('|', array_map(function ($type) use ($isBuiltin) {
                            if (!$type->isBuiltin()) {
                                $isBuiltin = false;
                            }
                            return $type->getName();
                        }, $returnType->getTypes()));
                    } elseif ($returnType instanceof \ReflectionNamedType) {
                        if ($returnType->isBuiltin()) {
                            $isBuiltin = true;
                            $methodInfo['returnType'] = (string)$returnType;
                        } else {
                            $returnTypeName = $returnType->getName();
                            if (strpos($returnTypeName, '\\') !== 0) {
                                if (strpos($returnTypeName, '\\') !== 0) {
                                    if ($returnTypeName == 'self') {
                                        $returnTypeName = '\\' . $interfaceName;
                                    } else {
                                        $returnTypeName = '\\' . $returnTypeName;
                                    }
                                }
                            }
                            $methodInfo['returnType'] = $returnTypeName;
                        }
                    } else {
                        $methodInfo['returnType'] = 'mixed';
                    }
                } else {
                    $methodInfo['returnType'] = 'void';
                }
                $methodInfo['returnTypeIsBuiltin'] = $isBuiltin;

                // 获取方法的注释信息
                $docComment = $method->getDocComment();
                $docCommentLines = explode("\n", $docComment);
                $methodInfo['docBlockStartLine'] = $method->getStartLine() - count($docCommentLines);
                $methodInfo['docBlockEndLine'] = $method->getStartLine() - 1;
                if ($docComment !== false) {
                    $docBlock = $factory->create($docComment);
                    $methodInfo['docBlock'] = [
                        'summary' => $docBlock->getSummary(),
                        'tags' => [],
                    ];
                    // 添加方法注释中的标签信息到结果数组
                    foreach ($docBlock->getTags() as $tag) {
                        $methodInfo['docBlock']['tags'][] = [
                            'name' => $tag->getName(),
                            'description' => (string) $tag,
                        ];
                    }
                }
                $interfaceInfo['methods'][] = $methodInfo;
            }
            $result = $interfaceInfo;
        } elseif (preg_match('/function\s+([a-zA-Z0-9_]+)\s*\(/', $fileContent)) {
            // 是函数文件
            $summary = '';
            if (preg_match('/\*\*(.*?)\*\//s', $fileContent, $m)) {
                $tmpArr = explode("\n", trim($m[1]));
                foreach ($tmpArr as $v) {
                    $v = trim($v, '* ');
                    if ($v != '') {
                        $summary = $v;
                        break;
                    }
                }
            }

            // 查找所有函数
            preg_match_all('/function\s+([a-zA-Z0-9_]+)\s*\(/', $fileContent, $matches);
            $functions = (array)$matches[1];

            foreach ($functions as $functionName) {
                $functionInfo = [
                    'type' => 'function',
                    'name' => '',
                    'parameters' => [],
                    'isStatic' => null,
                    'startLine' => null, // 默认函数起始行号为空
                    'endLine' => null, // 默认函数结束行号为空
                    'docBlockStartLine' => null,  // 注释起始行
                    'docBlockEndLine' => null,    // 注释结束行
                ];
                $functionInfo['name'] = $functionName;
                // 使用反射 API 获取函数注释
                try {
                    $reflector = new ReflectionFunction($functionName);
                } catch (\Throwable $th) {
                    continue;
                }
                $functionInfo['startLine'] = $reflector->getStartLine(); // 获取函数起始行号
                $functionInfo['endLine'] = $reflector->getEndLine(); // 获取函数结束行号
                $docComment = $reflector->getDocComment();
                // 查找注释的起始行和结束行
                $docCommentLines = explode("\n", $docComment);
                $functionInfo['docBlockStartLine'] = $reflector->getStartLine() - count($docCommentLines);
                $functionInfo['docBlockEndLine'] = $reflector->getStartLine() - 1;
                if ($docComment !== false) {
                    $docBlock = $factory->create($docComment);
                    // 将函数注释信息加入结果数组
                    $functionInfo['docBlock'] = [
                        'summary' => $docBlock->getSummary(),
                        'description' => (string) $docBlock->getDescription(),
                        'tags' => [],
                    ];
                    // 添加函数注释中的标签信息到结果数组
                    foreach ($docBlock->getTags() as $tag) {
                        $functionInfo['docBlock']['tags'][] = [
                            'name' => $tag->getName(),
                            'description' => (string) $tag,
                        ];
                    }
                }

                // 获取函数的参数信息（名称及类型）
                $isBuiltin = false;
                foreach ($reflector->getParameters() as $parameter) {
                    $parameterType = $parameter->getType();
                    // 处理参数类型为联合类型的情况
                    if ($parameterType instanceof \ReflectionUnionType) {
                        $isBuiltin = true;
                        $parameterTypeName = implode('|', array_map(function ($type) use ($isBuiltin) {
                            if (!$type->isBuiltin()) {
                                $isBuiltin = false;
                            }
                            return $type->getName();
                        }, $parameterType->getTypes()));
                    } elseif ($parameterType instanceof \ReflectionNamedType) {
                        // 检查参数类型是否为内置类型
                        if ($parameterType->isBuiltin()) {
                            $isBuiltin = true;
                            $parameterTypeName = (string)$parameterType;
                        } else {
                            $parameterTypeName = $parameterType->getName();
                            if (strpos($parameterTypeName, '\\') !== 0) {
                                $parameterTypeName = '\\' . $parameterTypeName;
                            }
                        }
                    } else {
                        $parameterTypeName = 'mixed';
                    }


                    // 检查是否是可变参数
                    $isVariadic = $parameter->isVariadic();

                    // 添加对默认值的获取
                    $default = '<phpdoc_null>';
                    if ($parameter->isDefaultValueAvailable()) {
                        $default = $parameter->getDefaultValue();
                    }

                    $functionInfo['parameters'][] = [
                        'name' => $parameter->getName(),
                        'type' => $parameterTypeName,
                        'default' => $default,
                        'isVariadic' => $isVariadic,
                        'isBuiltin' => $isBuiltin,
                    ];
                }

                // 获取函数的返回值类型
                $isBuiltin = false;
                $returnType = $reflector->getReturnType();
                if ($returnType) {
                    if ($returnType instanceof \ReflectionUnionType) {
                        $isBuiltin = true;
                        $functionInfo['returnType'] = implode('|', array_map(function ($type) use ($isBuiltin) {
                            if (!$type->isBuiltin()) {
                                $isBuiltin = false;
                            }
                            return $type->getName();
                        }, $returnType->getTypes()));
                    } elseif ($returnType instanceof \ReflectionNamedType) {
                        if ($returnType->isBuiltin()) {
                            $isBuiltin = true;
                            $functionInfo['returnType'] = (string)$returnType;
                        } else {
                            $returnTypeName = $returnType->getName();
                            if (strpos($returnTypeName, '\\') !== 0) {
                                $returnTypeName = '\\' . $returnTypeName;
                            }
                            $functionInfo['returnType'] = $returnTypeName;
                        }
                    } else {
                        $functionInfo['returnType'] = 'mixed';
                    }
                } else {
                    $functionInfo['returnType'] = 'void';
                }
                $functionInfo['returnTypeIsBuiltin'] = $isBuiltin;

                // 将函数信息加入结果数组
                $result[] = $functionInfo;
            }
            $result = [
                'codefile' => $filename,
                'type' => 'function',
                'name' => basename($filename),
                'namespace' => 'none',
                'functions' => $result,
                'docBlock' => [
                    'summary' => $summary,
                ],
            ];
        } else {
            // 没有找到类、接口或函数
            $result = null;
        }
        return $result;
    }

    public function getVisibility($reflector): string
    {
        if ($reflector->isPublic()) {
            return 'public';
        } elseif ($reflector->isProtected()) {
            return 'protected';
        } else {
            return 'private';
        }
    }
}
