<?php

namespace Kylin\Modules\Generators;

use Illuminate\Container\Container;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Str;
use Kylin\Modules\Exceptions\ModuleAlreadyExistsException;

/**
 * 模块生成器
 *
 * 负责生成新的模块结构和文件
 */
class ModuleGenerator
{
    /**
     * 创建一个新的模块生成器实例
     *
     * @param  Container  $app  应用实例
     * @param  string  $name  模块名称
     * @param  array  $options  生成器选项
     */
    public function __construct(
        private readonly Container $app,
        private readonly string $name,
        private readonly array $options = []
    ) {
        $this->files = $app['files'];
        $this->path = $this->getModulePath();
    }

    /**
     * 文件系统实例
     *
     * @var Filesystem
     */
    private Filesystem $files;

    /**
     * 模块路径
     *
     * @var string
     */
    private string $path;

    /**
     * 生成模块
     *
     * @throws ModuleAlreadyExistsException
     */
    public function generate(): void
    {
        $this->validateModuleDoesNotExist();
        $this->createDirectoryStructure();
        $this->generateFiles();
        $this->generateComposerFile();
    }

    /**
     * 验证模块不存在
     *
     * @throws ModuleAlreadyExistsException
     */
    protected function validateModuleDoesNotExist(): void
    {
        if ($this->files->exists($this->path) && !($this->options['force'] ?? false))
        {
            throw new ModuleAlreadyExistsException(
                "模块 [{$this->name}] 已存在于 {$this->path}"
            );
        }
    }

    /**
     * 创建目录结构
     */
    protected function createDirectoryStructure(): void
    {
        $directories = [
            $this->path,
            $this->path . '/src',
            $this->path . '/src/Providers',
            $this->path . '/database',
            $this->path . '/database/migrations',
            $this->path . '/database/seeders',
        ];
        
        if (!($this->options['plain'] ?? false)) {
            $directories = array_merge($directories, [
                $this->path . '/src/Http',
                $this->path . '/src/Http/Controllers',
                $this->path . '/src/Http/Middleware',
                $this->path . '/src/Models',
                $this->path . '/config',
                $this->path . '/routes',
                $this->path . '/resources',
                $this->path . '/resources/views',
                $this->path . '/resources/views/layouts',
                $this->path . '/resources/lang',
                $this->path . '/resources/assets',
                $this->path . '/resources/assets/js',
                $this->path . '/resources/assets/css',
            ]);
        }

        foreach ($directories as $directory) {
            if (!$this->files->isDirectory($directory)) {
                $this->files->makeDirectory($directory, 0755, true);
            }
        }
    }

    /**
     * 生成模块文件
     */
    protected function generateFiles(): void
    {
        if (!($this->options['plain'] ?? false)) {
            $this->generateController();
            $this->generateRoutes();
            $this->generateViews();
            $this->generateConfig();
        }
        
        $this->generateServiceProvider();
    }

    /**
     * 生成控制器文件
     */
    protected function generateController(): void
    {
        $controllerName = 'HomeController';
        $controllerPath = $this->path . '/src/Http/Controllers/' . $controllerName . '.php';

        $content = $this->files->get(__DIR__ . '/../../stubs/controller.stub');
        $content = str_replace('{{STUDLY_NAME}}', $this->getStudlyName(), $content);
        $content = str_replace('{{LOWER_NAME}}', $this->getLowerName(), $content);
        $content = str_replace('{{NAMESPACE}}', $this->getNamespace(), $content);

        $this->files->put($controllerPath, $content);
    }

    /**
     * 生成服务提供者文件
     */
    protected function generateServiceProvider(): void
    {
        $providerName = 'AppServiceProvider';
        $providerPath = $this->path . '/src/Providers/' . $providerName . '.php';

        $content = $this->files->get(__DIR__ . '/../../stubs/provider.stub');
        $content = str_replace('{{ namespace }}', $this->getNamespace(), $content);
        $content = str_replace('{{ class }}', $providerName, $content);

        $this->files->put($providerPath, $content);
    }

    /**
     * 生成路由文件
     */
    protected function generateRoutes(): void
    {
        // Web 路由
        $webRoutePath = $this->path . '/routes/web.php';
        $webRouteContent = $this->files->get(__DIR__ . '/../../stubs/routes.web.stub');
        $webRouteContent = str_replace('{{ namespace }}', $this->getNamespace(), $webRouteContent);
        $webRouteContent = str_replace('{{ lower_name }}', $this->getLowerName(), $webRouteContent);

        $this->files->put($webRoutePath, $webRouteContent);

        // API 路由
        $apiRoutePath = $this->path . '/routes/api.php';
        $apiRouteContent = $this->files->get(__DIR__ . '/../../stubs/routes.api.stub');
        $apiRouteContent = str_replace('{{ namespace }}', $this->getNamespace(), $apiRouteContent);
        $apiRouteContent = str_replace('{{ lower_name }}', $this->getLowerName(), $apiRouteContent);

        $this->files->put($apiRoutePath, $apiRouteContent);
    }

    /**
     * 生成视图文件
     */
    protected function generateViews(): void
    {
        // 主布局
        $masterViewPath = $this->path . '/resources/views/layouts/master.blade.php';
        $masterViewContent = $this->files->get(__DIR__ . '/../../stubs/views.master.stub');
        $masterViewContent = str_replace('{{STUDLY_NAME}}', $this->getStudlyName(), $masterViewContent);
        $masterViewContent = str_replace('{{LOWER_NAME}}', $this->getLowerName(), $masterViewContent);

        $this->files->put($masterViewPath, $masterViewContent);

        // 索引视图
        $indexViewPath = $this->path . '/resources/views/index.blade.php';
        $indexViewContent = $this->files->get(__DIR__ . '/../../stubs/views.index.stub');
        $indexViewContent = str_replace('{{STUDLY_NAME}}', $this->getStudlyName(), $indexViewContent);
        $indexViewContent = str_replace('{{LOWER_NAME}}', $this->getLowerName(), $indexViewContent);

        $this->files->put($indexViewPath, $indexViewContent);
    }

    /**
     * 生成配置文件
     */
    protected function generateConfig(): void
    {
        $configPath = $this->path . '/config/config.php';
        $configContent = $this->files->get(__DIR__ . '/../../stubs/config.stub');
        $configContent = str_replace('{{STUDLY_NAME}}', $this->getStudlyName(), $configContent);

        $this->files->put($configPath, $configContent);
    }

    /**
     * 生成 composer.json 文件
     */
    protected function generateComposerFile(): void
    {
        $composerPath = $this->path . '/composer.json';
        $composerContent = $this->files->get(__DIR__ . '/../../stubs/composer.stub');

        // 获取供应商名称和模块小写名称
        $vendor = strtolower($this->app['config']->get('modules.defaults.namespace', 'Kylin'));
        $lowerName = $this->getLowerName();
        $namespace = $this->getNamespace();
        $appFolderName = 'src';
        
        // 获取作者和版本信息
        $authorName = $this->app['config']->get('modules.defaults.author_name', '王康');
        $authorEmail = $this->app['config']->get('modules.defaults.author_email', 'earl.k.wang@wangk.cn');
        $version = $this->app['config']->get('modules.defaults.version', '1.0.0');

        // 替换模板变量
        $composerContent = str_replace('{{VENDOR}}', $vendor, $composerContent);
        $composerContent = str_replace('{{LOWER_NAME}}', $lowerName, $composerContent);
        $composerContent = str_replace('{{NAME}}', $lowerName, $composerContent);
        $composerContent = str_replace('{{NAMESPACE}}', $namespace, $composerContent);
        $composerContent = str_replace('{{MODULE_NAMESPACE}}', $this->app['config']->get('modules.defaults.namespace', 'Kylin'), $composerContent);
        $composerContent = str_replace('{{STUDLY_NAME}}', $this->getStudlyName(), $composerContent);
        $composerContent = str_replace('{{APP_FOLDER_NAME}}', $appFolderName, $composerContent);
        $composerContent = str_replace('{{AUTHOR_NAME}}', $authorName, $composerContent);
        $composerContent = str_replace('{{AUTHOR_EMAIL}}', $authorEmail, $composerContent);
        $composerContent = str_replace('{{VERSION}}', $version, $composerContent);

        $this->files->put($composerPath, $composerContent);
    }

    /**
     * 获取模块路径
     */
    public function getPath(): string
    {
        return $this->path;
    }

    /**
     * 获取模块路径
     */
    protected function getModulePath(): string
    {
        return $this->app['config']->get('modules.path', base_path('packages')) . '/' . $this->getLowerName();
    }

    /**
     * 获取首字母大写的名称
     */
    protected function getStudlyName(): string
    {
        return Str::studly($this->name);
    }

    /**
     * 获取小写名称
     */
    protected function getLowerName(): string
    {
        return strtolower($this->name);
    }

    /**
     * 获取模块命名空间
     */
    protected function getNamespace(): string
    {
        $baseNamespace = $this->app['config']->get('modules.defaults.namespace', 'Kylin');
        return $baseNamespace . '\\' . $this->getStudlyName();
    }
}