<?php
// +----------------------------------------------------------------------
// | onezan-admin 快速开发的管理平台
// +----------------------------------------------------------------------
// | 官方网址：https://www.onezan.cn
// +----------------------------------------------------------------------
// | onezan团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: 543885307@qq.com
// +----------------------------------------------------------------------
namespace app\service\domain\admin\system;

use Core\service\aggregator\AdminNavigationAggregator;
use Core\service\aggregator\AdminPermissionAggregator;
use Core\service\aggregator\ChannelMessageAggregator;
use Core\service\aggregator\SettingsAggregator;
use Core\service\installer\ApplicationInstaller;
use Core\service\menu\MenuOverrideService;
use Core\service\module\CoreModuleService;
use Core\service\registry\LifecycleBootstrapSnapshot;
use Core\service\registry\MenuRegistry;
use Core\service\registry\MessageRegistry;
use Core\service\registry\PermissionRegistry;
use Core\service\registry\SettingsRegistry;
use app\service\domain\admin\CoreAdminPermissionService;
use Core\service\BaseCoreService;
use app\model\AdminUser;
use app\repository\module\ModuleManifestRepository;
use app\repository\system\ConfigRepository;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use FilesystemIterator;


/**
 * 平台聚合服务
 * 聚合导航、权限、设置、消息、菜单覆盖等平台级能力
 * @package app\service\domain\admin\system
 */
class CorePlatformService extends BaseCoreService
{
    /**
     * 获取所有应用
     * @return array
     */
    public function applications(): array
    {
        return ['code' => 0, 'data' => $this->installer()->status()];
    }


    /**
     * 安装应用
     * @param string $code
     * @return array
     */
    public function installApplication(string $code): array
    {
        $result = $this->installer()->install($code);

        return [
            'code' => 0,
            'msg' => $result['message'] ?? '',
            'data' => array_merge($result, $this->installer()->status()),
        ];
    }

    /**
     * 卸载应用
     * @param string $code
     * @param bool $dropTables
     * @return array
     */
    public function uninstallApplication(string $code, bool $dropTables = false): array
    {
        $result = $this->installer()->uninstall($code, $dropTables);

        if (isset($result['error'])) {
            return ['code' => 1, 'msg' => $result['error'], 'data' => $result];
        }

        if (!$dropTables && $result['installed'] === false) {

            $this->sync();
        }

        return [
            'code' => 0,
            'msg' => $result['message'] ?? '',
            'data' => array_merge($result, $this->installer()->status()),
        ];
    }

    /**
     * 获取应用数据库表
     * @param string $code
     * @return array
     */
    public function getApplicationTables(string $code): array
    {
        return ['code' => 0, 'data' => $this->installer()->tableList($code)];
    }


    /**
     * 切换应用状态
     * @param string $code
     * @param bool $enabled
     * @return array
     */
    public function toggleApplication(string $code, bool $enabled): array
    {
        if ($enabled) {
            $result = $this->installer()->enable($code);
        } else {
            $result = $this->installer()->disable($code);
        }

        if (isset($result['error'])) {
            return ['code' => 1, 'msg' => $result['error'], 'data' => $result];
        }

        $this->sync();

        return [
            'code' => 0,
            'msg' => $enabled ? '' : '',
            'data' => $this->installer()->status(),
        ];
    }

    /**
     * 获取应用插件
     * @param string $appCode
     * @return array
     */
    public function getApplicationPlugins(string $appCode): array
    {
        $allModules = $this->moduleRepo()->getAll('plugin');
        $plugins = [];
        $prefix = $appCode . '.';

        foreach ($allModules as $module) {
            $code = (string)$module['code'];
            if (!str_starts_with($code, $prefix)) {
                continue;
            }

            $plugins[] = [
                'code' => $code,
                'name' => (string)$module['name'],
                'description' => (string)($module['description'] ?? ''),
                'version' => (string)($module['version'] ?? ''),
                'type' => (string)($module['type'] ?? 'plugin'),
                'status' => (int)($module['status'] ?? 1),
            ];
        }

        return ['code' => 0, 'data' => $plugins];
    }

    /**
     * 切换插件状态
     * @param string $code
     * @param bool $enabled
     * @return array
     */
    public function togglePlugin(string $code, bool $enabled): array
    {
        $manifest = $this->moduleRepo()->findByCode($code);
        if (!$manifest) {
            return ['code' => 1, 'msg' => ''];
        }

        $status = $enabled ? 1 : 0;
        $this->moduleRepo()->updateStatus($code, $status);
        $this->sync();

        return ['code' => 0, 'msg' => $enabled ? '' : ''];
    }

    /**
     * 获取导航菜单
     * @param AdminUser $user
     * @return array
     */

    public function navigation(AdminUser $user): array
    {
        $permissions = $this->permissionService()->getGrantedPermissionsForUser($user);

        return [
            'code' => 0,
            'data' => [
                'menus' => $this->navigationAggregator()->build($permissions),
                'permissions' => $permissions,
            ],
        ];
    }


    /**
     * 获取菜单配置
     * @return array
     */

    public function menuConfig(): array
    {
        return [
            'code' => 0,
            'data' => [
                'items' => $this->menuOverrideService()->getConfigList(),
            ],
        ];
    }


    /**
     * 保存菜单配置
     * @param array $items
     * @return array
     */

    public function saveMenuConfig(array $items): array
    {
        return [
            'code' => 0,
            'msg' => '',
            'data' => [
                'items' => $this->menuOverrideService()->saveConfigList($items),
            ],
        ];
    }


    /**
     * 重置菜单配置
     * @return array
     */

    public function resetMenuConfig(): array
    {
        return [
            'code' => 0,
            'msg' => '',
            'data' => [
                'items' => $this->menuOverrideService()->reset(),
            ],
        ];
    }

    /**
     * 获取消息
     * @return array
     */


    public function messages(): array
    {
        return ['code' => 0, 'data' => $this->messageAggregator()->build()];
    }


    /**
     * 获取设置
     * @param AdminUser $user
     * @return array
     */

    public function settings(AdminUser $user): array
    {
        $permissions = $this->permissionService()->getGrantedPermissionsForUser($user);
        return ['code' => 0, 'data' => $this->settingsAggregator()->build($permissions)];
    }

    /**
     * 获取权限
     * @return array
     */

    public function permissions(): array
    {
        return ['code' => 0, 'data' => $this->permissionAggregator()->build()];
    }


    /**
     * 同步平台缓存
     * @return array
     */

    public function sync(): array
    {
        $registeredModules = $this->moduleService()->initManifests();
        $snapshot = $this->writeLifecycleBootstrapSnapshot();
        $cleared = $this->clearRuntimeDirectories();
        $summary = [
            'updated_at' => date('Y-m-d H:i:s'),
            'applications' => [
                'installed' => $this->installer()->status()['installed'],
                'available' => $this->installer()->status()['available'],
            ],
            'counts' => [
                'menus' => count($this->menuRegistry()->all()),
                'messages' => count($this->messageRegistry()->all()),
                'settings' => count($this->settingsRegistry()->all()),
                'permissions' => count($this->permissionRegistry()->getFlat()),
                'module_manifests' => count($registeredModules),
            ],
            'module_codes' => array_values($registeredModules),
            'runtime' => [
                'lifecycle_bootstrap' => [
                    'installed_apps' => $snapshot['installed_apps'],
                    'module_count' => count($snapshot['module_statuses']),
                ],
                'cleared_directories' => $cleared,
            ],
        ];

        $this->configRepository()->setJson('platform_cache_refresh_meta', $summary, '');

        return ['code' => 0, 'msg' => '', 'data' => $summary];
    }

    /**
     * 写入生命周期引导快照
     * @return array
     */

    private function writeLifecycleBootstrapSnapshot(): array
    {
        $installedApplicationCodes = [];
        foreach ((array)($this->installer()->status()['enabled'] ?? []) as $appCode) {
            if (is_array($appCode)) {
                $appCode = $appCode['code'] ?? '';
            }

            if (is_string($appCode) && trim($appCode) !== '') {
                $installedApplicationCodes[] = trim($appCode);
            }
        }

        $snapshot = [
            'installed_apps' => array_values(array_unique($installedApplicationCodes)),
            'module_statuses' => [],
        ];

        foreach ($this->moduleRepo()->getAll() as $manifest) {
            $code = trim((string)($manifest['code'] ?? ''));
            if ($code === '') {
                continue;
            }

            $snapshot['module_statuses'][$code] = (int)($manifest['status'] ?? 1) === 1 ? 1 : 0;
        }

        LifecycleBootstrapSnapshot::save($this->app->getRootPath(), $snapshot);

        return $snapshot;
    }

    /**
     * 清除运行时目录
     * @return array
     */

    private function clearRuntimeDirectories(): array
    {
        $runtimePath = rtrim(app()->getRootPath(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'runtime';
        $targets = ['cache', 'log'];
        $cleared = [];

        foreach ($targets as $dir) {
            $targetPath = $runtimePath . DIRECTORY_SEPARATOR . $dir;
            if (!is_dir($targetPath)) {
                continue;
            }

            $this->clearDirectoryContents($targetPath);
            $cleared[] = str_replace(DIRECTORY_SEPARATOR, '/', 'api/runtime/' . $dir);
        }

        return $cleared;
    }

    /**
     * 清除目录内容
     * @param string $directory
     * @return void
     */

    private function clearDirectoryContents(string $directory): void
    {
        $iterator = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($directory, FilesystemIterator::SKIP_DOTS),
            RecursiveIteratorIterator::CHILD_FIRST
        );

        foreach ($iterator as $item) {
            $path = $item->getPathname();
            if ($item->isDir()) {
                @rmdir($path);
                continue;
            }

            @unlink($path);
        }
    }

    /**
     * 获取导航聚合器
     * @return AdminNavigationAggregator
     */

    private function navigationAggregator(): AdminNavigationAggregator
    {
        return $this->app->make(AdminNavigationAggregator::class);
    }

    /**
     * 获取消息聚合器
     * @return ChannelMessageAggregator
     */

    private function messageAggregator(): ChannelMessageAggregator
    {
        return $this->app->make(ChannelMessageAggregator::class);
    }

    /**
     * 获取设置聚合器
     * @return SettingsAggregator
     */

    private function settingsAggregator(): SettingsAggregator
    {
        return $this->app->make(SettingsAggregator::class);
    }

    /**
     * 获取权限聚合器
     * @return AdminPermissionAggregator
     */

    private function permissionAggregator(): AdminPermissionAggregator
    {
        return $this->app->make(AdminPermissionAggregator::class);
    }

    /**
     * 获取应用安装器
     * @return ApplicationInstaller
     */

    private function installer(): ApplicationInstaller
    {
        return $this->app->make(ApplicationInstaller::class);
    }

    /**
     * 获取模块服务
     * @return CoreModuleService
     */

    private function moduleService(): CoreModuleService
    {
        return $this->app->make(CoreModuleService::class);
    }

    /**
     * 获取权限服务
     * @return CoreAdminPermissionService
     */

    private function permissionService(): CoreAdminPermissionService
    {
        return $this->app->make(CoreAdminPermissionService::class);
    }

    /**
     * 获取菜单注册器
     * @return MenuRegistry
     */

    private function menuRegistry(): MenuRegistry
    {
        return $this->app->make(MenuRegistry::class);
    }

    /**
     * 获取消息注册器
     * @return MessageRegistry
     */

    private function messageRegistry(): MessageRegistry
    {
        return $this->app->make(MessageRegistry::class);
    }

    /**
     * 获取设置注册器
     * @return SettingsRegistry
     */

    private function settingsRegistry(): SettingsRegistry
    {
        return $this->app->make(SettingsRegistry::class);
    }

    /**
     * 获取权限注册器
     * @return PermissionRegistry
     */

    private function permissionRegistry(): PermissionRegistry
    {
        return $this->app->make(PermissionRegistry::class);
    }

    /**
     * 获取配置仓库
     * @return ConfigRepository
     */

    private function configRepository(): ConfigRepository
    {
        return $this->app->make(ConfigRepository::class);
    }

    /**
     * 获取菜单覆盖服务
     * @return MenuOverrideService
     */

    private function menuOverrideService(): MenuOverrideService
    {
        return $this->app->make(MenuOverrideService::class);
    }

    /**
     * 获取模块仓库
     * @return ModuleManifestRepository
     */

    private function moduleRepo(): ModuleManifestRepository
    {
        return $this->app->make(ModuleManifestRepository::class);
    }
}