<?php

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

return new class extends Migration
{
    private const RESOURCE_CODE = 'admin.settings.batch-update';

    private const CLONE_BINDINGS_FROM = 'admin.settings.update';

    public function up(): void
    {
        $now = Carbon::now();
        $resource = collect(AdminAuthorizationRegistry::resources())
            ->first(fn (array $item): bool => $item['code'] === self::RESOURCE_CODE);

        if ($resource === null) {
            return;
        }

        $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();

        $sourceResourceId = DB::table('admin_api_resources')
            ->where('code', self::CLONE_BINDINGS_FROM)
            ->value('id');

        if ($sourceResourceId !== null) {
            $bindings = DB::table('admin_api_resource_bindings')
                ->where('api_resource_id', (int) $sourceResourceId)
                ->get(['menu_action_id']);

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

        if (Schema::hasTable('admin_role_api_resources')) {
            $roleResourceRows = DB::table('admin_role_menu_actions as rma')
                ->join('admin_api_resource_bindings as arb', 'arb.menu_action_id', '=', 'rma.menu_action_id')
                ->where('arb.api_resource_id', (int) $resourceId)
                ->select('rma.role_id')
                ->distinct()
                ->get();

            foreach ($roleResourceRows as $row) {
                DB::table('admin_role_api_resources')->updateOrInsert([
                    'role_id' => (int) $row->role_id,
                    'api_resource_id' => (int) $resourceId,
                ], []);
            }
        }
    }

    public function down(): void
    {
        $resourceId = DB::table('admin_api_resources')->where('code', self::RESOURCE_CODE)->value('id');
        if ($resourceId === null) {
            return;
        }

        if (Schema::hasTable('admin_role_api_resources')) {
            DB::table('admin_role_api_resources')->where('api_resource_id', (int) $resourceId)->delete();
        }
        DB::table('admin_api_resource_bindings')->where('api_resource_id', (int) $resourceId)->delete();
        DB::table('admin_api_resources')->where('id', (int) $resourceId)->delete();
    }
};
