<?php

namespace YouHuJun\Tool\App\Console\Commands;

use YouHuJun\Tool\App\Exceptions\CommonException;

class GeneratorCommand
{
    /**
     * @var string Facade 模板路径
     */
    private string $facadeStubPath;

    /**
     * @var string Service 模板路径
     */
    private string $serviceStubPath;

    /**
     * @var string 项目根目录
     */
    private string $basePath;

    /**
     * @var string 基础命名空间
     */
    private string $baseNamespace;

    public function __construct()
    {
        $this->basePath = dirname(__DIR__, 4);
        $this->facadeStubPath = $this->basePath . '/src/App/Console/Commands/stubs/facade.stub';
        $this->serviceStubPath = $this->basePath . '/src/App/Console/Commands/stubs/service.stub';
        $this->baseNamespace = 'YouHuJun\\Tool\\App';
    }

    /**
     * 解析路径并执行对应操作
     *
     * @param string $path 路径,如: Wechat/Official/WechatOfficialWebAuth 或 Calendar
     * @param string $description 描述信息(仅用于生成 Service)
     * @return array 生成的文件路径
     * @throws CommonException
     */
    public function generate(string $path, string $description = ''): array
    {
        $path = trim($path, '/\\');
        // 统一使用正斜杠分割路径
        $path = str_replace('\\', '/', $path);
        $parts = explode('/', $path);

        if (count($parts) < 1) {
            throw new CommonException('ParameterError');
        }

        $className = array_pop($parts); // 最后一段永远是类名(模块名)

        // 检查第一部分是否是版本号(V1, V2等)
        $version = '';
        if (!empty($parts) && preg_match('/^V\d+$/', $parts[0])) {
            $version = array_shift($parts); // 提取版本号并从数组中移除
        }

        $modulePath = implode('/', $parts); // 剩下的部分是模块路径

        // 同时生成 Facade 和 Service
        $generatedFiles[] = $this->generateFacadeFile($className, $modulePath, $version);
        $generatedFiles[] = $this->generateServiceFile($className, $modulePath, $version, $description);

        return $generatedFiles;
    }

    /**
     * 生成 Facade 文件
     */
    private function generateFacadeFile(string $className, string $modulePath, string $version = 'V1'): string
    {
        // 解析模块路径
        $modulePath = trim($modulePath, '/\\');
        $moduleNamespace = $modulePath ? '\\' . str_replace('/', '\\', $modulePath) : '';

        // 清理类名
        $className = $this->sanitizeClassName($className);
        $facadeClassName = $className;

        // 确保以 Facade 结尾(单数形式)
        $facadeClassName = preg_replace('/Facades?$/', '', $facadeClassName);
        $facadeClassName .= 'Facade';

        // 对应的 Service 类名
        $serviceClassName = $className . 'Service';

        // 生成目录路径 - 基础路径是 Facade, 不包含 V1
        $facadeDir = $this->basePath . '/src/App/Facades/' . $version . ($modulePath ? '/' . $modulePath : '');

        // 创建目录
        $this->ensureDirectoryExists($facadeDir);

        // 文件路径
        $facadeFile = $facadeDir . '/' . $facadeClassName . '.php';

        // 检查文件是否已存在
        if (file_exists($facadeFile)) {
            throw new CommonException('FileExistsError');
        }

        // 生成内容
        $stub = file_get_contents($this->facadeStubPath);
        $content = str_replace(
            [
                '{{Namespace}}',
                '{{ModulePath}}',
                '{{FacadeClass}}',
                '{{ServiceClass}}',
            ],
            [
                $this->baseNamespace,
                $moduleNamespace,
                $facadeClassName,
                $serviceClassName,
            ],
            $stub
        );
        file_put_contents($facadeFile, $content);

        return $facadeFile;
    }

    /**
     * 生成 Service 文件
     */
    private function generateServiceFile(string $className, string $modulePath, string $version = 'V1', string $description = ''): string
    {
        // 解析模块路径
        $modulePath = trim($modulePath, '/\\');
        $moduleNamespace = $modulePath ? '\\' . str_replace('/', '\\', $modulePath) : '';

        // 清理类名
        $className = $this->sanitizeClassName($className);

        // 确保以 Service 结尾
        $className = preg_replace('/Service$/', '', $className);
        $className .= 'Service';

        // 生成目录路径 - 基础路径是 Service, 不包含 V1
        $serviceDir = $this->basePath . '/src/App/Services/' . $version . ($modulePath ? '/' . $modulePath : '');

        // 创建目录
        $this->ensureDirectoryExists($serviceDir);

        // 文件路径
        $serviceFile = $serviceDir . '/' . $className . '.php';

        // 检查文件是否已存在
        if (file_exists($serviceFile)) {
            throw new CommonException('FileExistsError');
        }

        // 生成内容
        $stub = file_get_contents($this->serviceStubPath);
        $content = str_replace(
            [
                '{{Namespace}}',
                '{{ModulePath}}',
                '{{ServiceClass}}',
                '{{Description}}',
                '{{Date}}',
                '{{Year}}',
            ],
            [
                $this->baseNamespace,
                $moduleNamespace,
                $className,
                $description ?: '自动生成的服务类',
                date('Y-m-d H:i:s'),
                date('Y'),
            ],
            $stub
        );
        file_put_contents($serviceFile, $content);

        return $serviceFile;
    }

    /**
     * 确保目录存在
     */
    private function ensureDirectoryExists(string $directory): void
    {
        if (!is_dir($directory)) {
            mkdir($directory, 0755, true);
        }
    }

    /**
     * 清理类名
     */
    private function sanitizeClassName(string $name): string
    {
        // 只保留字母、数字和下划线
        return preg_replace('/[^a-zA-Z0-9_]/', '', $name);
    }
}