<?php

use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use App\Support\AdminAuthorizationRegistry;
use Illuminate\Database\Migrations\Migration;

/**
 * 代理「节点 / 角色 / 账号」查看与管理拆分为独立 permission_code，避免只勾一项却获得全部管理能力。
 */
return new class extends Migration
{
    public function up(): void
    {
        $now = Carbon::now();
        $viewActionId = DB::table('admin_action_catalog')->where('code', 'view')->value('id');
        $manageActionId = DB::table('admin_action_catalog')->where('code', 'manage')->value('id');
        if ($viewActionId === null || $manageActionId === null) {
            return;
        }

        $agentMenuId = (int) DB::table('admin_menus')->where('code', 'system.agents')->value('id');
        if ($agentMenuId === 0) {
            return;
        }

        $rolesMenuId = $this->ensureChildMenu($agentMenuId, 'system.agents.roles', '代理角色', $now);
        $usersMenuId = $this->ensureChildMenu($agentMenuId, 'system.agents.users', '代理账号', $now);

        $this->ensureMenuAction((int) $rolesMenuId, (int) $viewActionId, 'agent.role.view', '代理角色查看', $now);
        $this->ensureMenuAction((int) $rolesMenuId, (int) $manageActionId, 'agent.role.manage', '代理角色管理', $now);
        $this->ensureMenuAction((int) $usersMenuId, (int) $viewActionId, 'agent.user.view', '代理账号查看', $now);
        $this->ensureMenuAction((int) $usersMenuId, (int) $manageActionId, 'agent.user.manage', '代理账号管理', $now);

        $menuActionIds = DB::table('admin_menu_actions')->pluck('id', 'permission_code');
        $nodeViewId = $menuActionIds['agent.node.view'] ?? null;
        $nodeManageId = $menuActionIds['agent.node.manage'] ?? null;
        $roleViewId = $menuActionIds['agent.role.view'] ?? null;
        $roleManageId = $menuActionIds['agent.role.manage'] ?? null;
        $userViewId = $menuActionIds['agent.user.view'] ?? null;
        $userManageId = $menuActionIds['agent.user.manage'] ?? null;

        if ($nodeViewId !== null && $roleViewId !== null && $userViewId !== null) {
            $roleIdsWithNodeView = DB::table('admin_role_menu_actions')
                ->where('menu_action_id', (int) $nodeViewId)
                ->pluck('role_id')
                ->unique()
                ->all();

            foreach ($roleIdsWithNodeView as $roleId) {
                foreach ([$roleViewId, $userViewId] as $actionId) {
                    $this->attachRoleMenuAction((int) $roleId, (int) $actionId, $now);
                }
            }
        }

        if ($nodeManageId !== null && $roleManageId !== null && $userManageId !== null) {
            $roleIdsWithNodeManage = DB::table('admin_role_menu_actions')
                ->where('menu_action_id', (int) $nodeManageId)
                ->pluck('role_id')
                ->unique()
                ->all();

            foreach ($roleIdsWithNodeManage as $roleId) {
                foreach ([$roleManageId, $userManageId] as $actionId) {
                    $this->attachRoleMenuAction((int) $roleId, (int) $actionId, $now);
                }
            }
        }

        $resources = array_values(array_filter(
            AdminAuthorizationRegistry::resources(),
            static fn (array $resource): bool => str_starts_with((string) $resource['code'], 'admin.agent-')
        ));

        foreach ($resources as $resource) {
            $resourceId = DB::table('admin_api_resources')->where('code', $resource['code'])->value('id');
            if ($resourceId === null) {
                continue;
            }

            DB::table('admin_api_resource_bindings')
                ->where('api_resource_id', (int) $resourceId)
                ->delete();

            foreach ($resource['permission_codes'] ?? [] as $permissionCode) {
                $menuActionId = $menuActionIds[$permissionCode] ?? null;
                if ($menuActionId === null) {
                    continue;
                }

                DB::table('admin_api_resource_bindings')->insert([
                    'api_resource_id' => (int) $resourceId,
                    'menu_action_id' => (int) $menuActionId,
                    'created_at' => $now,
                    'updated_at' => $now,
                ]);
            }
        }
    }

    private function ensureChildMenu(int $parentId, string $code, string $name, Carbon $now): int
    {
        $existing = DB::table('admin_menus')->where('code', $code)->value('id');
        if ($existing !== null) {
            return (int) $existing;
        }

        return (int) DB::table('admin_menus')->insertGetId([
            'parent_id' => $parentId,
            'menu_type' => 'button',
            'code' => $code,
            'name' => $name,
            'path' => null,
            'route_name' => null,
            'component' => null,
            'icon' => null,
            'active_menu_code' => 'system.agents',
            'sort_order' => 0,
            'is_visible' => false,
            'is_cache' => false,
            'is_external' => false,
            'status' => 1,
            'meta_json' => null,
            'created_at' => $now,
            'updated_at' => $now,
        ]);
    }

    private function ensureMenuAction(int $menuId, int $actionId, string $permissionCode, string $name, Carbon $now): void
    {
        if (DB::table('admin_menu_actions')->where('permission_code', $permissionCode)->exists()) {
            return;
        }

        DB::table('admin_menu_actions')->insert([
            'menu_id' => $menuId,
            'action_id' => $actionId,
            'permission_code' => $permissionCode,
            'name' => $name,
            'status' => 1,
            'created_at' => $now,
            'updated_at' => $now,
        ]);
    }

    private function attachRoleMenuAction(int $roleId, int $menuActionId, Carbon $now): void
    {
        $exists = DB::table('admin_role_menu_actions')
            ->where('role_id', $roleId)
            ->where('menu_action_id', $menuActionId)
            ->exists();

        if ($exists) {
            return;
        }

        DB::table('admin_role_menu_actions')->insert([
            'role_id' => $roleId,
            'menu_action_id' => $menuActionId,
        ]);
    }

    public function down(): void
    {
        $codes = ['agent.role.view', 'agent.role.manage', 'agent.user.view', 'agent.user.manage'];
        $actionIds = DB::table('admin_menu_actions')->whereIn('permission_code', $codes)->pluck('id')->all();

        if ($actionIds !== []) {
            DB::table('admin_role_menu_actions')->whereIn('menu_action_id', $actionIds)->delete();
            DB::table('admin_api_resource_bindings')->whereIn('menu_action_id', $actionIds)->delete();
            DB::table('admin_menu_actions')->whereIn('permission_code', $codes)->delete();
        }

        DB::table('admin_menus')->whereIn('code', ['system.agents.roles', 'system.agents.users'])->delete();
    }
};
