<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
use App\Models\AppModel;
use App\Models\AdminMenu;

/**
 * 应用菜单 code 字段数据回填迁移
 *
 * 遍历所有已安装应用的 manifest，按 path 匹配现有菜单并回填 code：
 * - manifest 中声明了 code 的，使用 manifest.code
 * - manifest 中未声明 code 的，按 path slug 化生成
 * - 应用已删除 manifest 中的菜单项但数据库残留的，按 path slug 化生成
 *
 * 幂等性：仅更新 code 为 NULL 的记录，重复执行安全。
 */
return new class extends Migration
{
    public function up(): void
    {
        // 遍历所有已安装应用，按 manifest 回填 code
        foreach (AppModel::all() as $app) {
            $manifest = $app->manifest ?? [];

            $this->backfillFromManifest($app->app_id, $manifest['menus'] ?? [], 'admin');
            $this->backfillFromManifest($app->app_id, $manifest['user_menus'] ?? [], 'user');
            $this->backfillFromManifest($app->app_id, $manifest['home_menus'] ?? [], 'home');
        }

        // 对未匹配到 manifest 的孤立菜单（如 manifest 项已被删除但数据库残留），按 path slug 化
        AdminMenu::whereNull('code')->chunkById(200, function ($menus) {
            foreach ($menus as $menu) {
                $code = $this->slugifyPath($menu->path);
                $code = $this->ensureUniqueCode($code, $menu->app_id, $menu->terminal_type, $menu->id);
                $menu->update(['code' => $code]);
            }
        });
    }

    private function backfillFromManifest(string $appId, array $items, string $terminalType): void
    {
        foreach ($items as $item) {
            $path = $item['path'] ?? '';
            $code = $item['code'] ?? $this->slugifyPath($path);

            if (empty($code)) {
                // path 为空的顶级分组菜单，使用 app_id + terminalType 组合
                $code = $this->slugifyPath($appId . '_' . $terminalType);
            }

            AdminMenu::where('app_id', $appId)
                ->where('terminal_type', $terminalType)
                ->where('path', $path)
                ->whereNull('code')
                ->update(['code' => $code]);

            if (!empty($item['children'])) {
                $this->backfillFromManifest($appId, $item['children'], $terminalType);
            }
        }
    }

    private function slugifyPath(?string $path): string
    {
        if (empty($path)) {
            return '';
        }
        if ($path === '/') {
            return 'home';
        }
        $slug = strtolower(trim($path, '/'));
        $slug = preg_replace('/[^a-z0-9]+/', '_', $slug);
        $slug = trim($slug, '_');
        return $slug ?: 'root';
    }

    private function ensureUniqueCode(string $code, ?string $appId, string $terminalType, int $excludeId): string
    {
        if (empty($code)) {
            $code = 'menu_' . $excludeId;
        }

        $original = $code;
        $i = 1;
        while (AdminMenu::where('app_id', $appId)
            ->where('terminal_type', $terminalType)
            ->where('code', $code)
            ->where('id', '!=', $excludeId)
            ->exists()) {
            $code = $original . '_' . $i++;
        }
        return $code;
    }

    public function down(): void
    {
        // 数据回填不可逆，down 时不操作数据
        // 字段删除由结构迁移的 down() 处理
    }
};
