<?php

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

/**
 * 代理账单 / 线路开通等 API 写入 admin_api_resources，并补齐 settlement.agent.* menu_action。
 */
return new class extends Migration
{
    /** @var list<string> */
    private const RESOURCE_CODE_PREFIXES = [
        'admin.settlement-bills.',
        'admin.settlement-periods.',
        'admin.settlement-payments.',
        'admin.settlement-adjustments.',
        'admin.settlement-reports.',
        'admin.credit-ledger.',
        'admin.agent-lines.',
        'admin.agent-nodes.profile.',
    ];

    /** @var list<string> */
    private const MENU_ACTION_CODES = [
        'settlement.agent.view',
        'settlement.agent.manage',
        'agent.line.provision',
        'agent.profile.manage',
    ];

    public function up(): void
    {
        AdminAgentLineSettlementPermissionMenuActionSync::syncMissing();

        $now = Carbon::now();
        $menuActionIds = DB::table('admin_menu_actions')->pluck('id', 'permission_code');

        $resources = array_values(array_filter(
            AdminAuthorizationRegistry::resources(),
            static fn (array $resource): bool => self::matchesResourceCode((string) $resource['code']),
        ));

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

            $payload = [
                'module_code' => $resource['module_code'],
                'name' => $resource['name'],
                'http_method' => $resource['http_method'],
                'uri_pattern' => $resource['uri_pattern'],
                'route_name' => $resource['route_name'],
                'auth_mode' => $resource['auth_mode'],
                'is_audit_required' => $resource['is_audit_required'],
                'status' => 1,
                'meta_json' => null,
                'updated_at' => $now,
            ];

            if ($resourceId === null) {
                $resourceId = DB::table('admin_api_resources')->insertGetId($payload + [
                    'code' => $resource['code'],
                    'created_at' => $now,
                ]);
            } else {
                DB::table('admin_api_resources')
                    ->where('id', (int) $resourceId)
                    ->update($payload);
            }

            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,
                ]);
            }
        }

        $this->grantSuperAdminMenuActions();
    }

    public function down(): void
    {
        foreach (AdminAuthorizationRegistry::resources() as $resource) {
            if (! self::matchesResourceCode((string) $resource['code'])) {
                continue;
            }

            $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();
            DB::table('admin_api_resources')->where('id', (int) $resourceId)->delete();
        }
    }

    private static function matchesResourceCode(string $code): bool
    {
        foreach (self::RESOURCE_CODE_PREFIXES as $prefix) {
            if (str_starts_with($code, $prefix)) {
                return true;
            }
        }

        return false;
    }

    private function grantSuperAdminMenuActions(): void
    {
        $superRoleId = DB::table('admin_roles')->where('slug', 'super_admin')->value('id');
        if ($superRoleId === null) {
            return;
        }

        $menuActionIds = DB::table('admin_menu_actions')
            ->whereIn('permission_code', self::MENU_ACTION_CODES)
            ->pluck('id');

        foreach ($menuActionIds as $menuActionId) {
            DB::table('admin_role_menu_actions')->updateOrInsert([
                'role_id' => (int) $superRoleId,
                'menu_action_id' => (int) $menuActionId,
            ]);
        }

        if (! Schema::hasTable('admin_role_legacy_permissions')) {
            return;
        }

        foreach (['prd.settlement.agent.view', 'prd.settlement.agent.manage', 'prd.agent-line.provision', 'prd.agent.profile.manage'] as $slug) {
            DB::table('admin_role_legacy_permissions')->updateOrInsert([
                'role_id' => (int) $superRoleId,
                'permission_slug' => $slug,
            ], []);
        }
    }
};
