<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        if (! Schema::hasTable('findings') || ! Schema::hasTable('inventory_sync_runs') || ! Schema::hasTable('operation_runs')) {
            return;
        }

        if (! Schema::hasColumn('findings', 'baseline_operation_run_id') || ! Schema::hasColumn('findings', 'current_operation_run_id')) {
            return;
        }

        DB::table('findings')
            ->select(['id', 'baseline_run_id', 'current_run_id', 'baseline_operation_run_id', 'current_operation_run_id'])
            ->orderBy('id')
            ->chunkById(500, function (Collection $rows): void {
                $legacyRunIds = $rows
                    ->flatMap(function (object $row): array {
                        return [
                            $row->baseline_run_id,
                            $row->current_run_id,
                        ];
                    })
                    ->filter(fn (mixed $id): bool => is_numeric($id))
                    ->map(fn (mixed $id): int => (int) $id)
                    ->unique()
                    ->values();

                if ($legacyRunIds->isEmpty()) {
                    return;
                }

                $operationRunIdByLegacyRunId = DB::table('inventory_sync_runs')
                    ->whereIn('id', $legacyRunIds->all())
                    ->whereNotNull('operation_run_id')
                    ->pluck('operation_run_id', 'id')
                    ->map(fn (mixed $id): int => (int) $id);

                if ($operationRunIdByLegacyRunId->isEmpty()) {
                    return;
                }

                $existingOperationRunIds = DB::table('operation_runs')
                    ->whereIn('id', $operationRunIdByLegacyRunId->values()->unique()->all())
                    ->pluck('id')
                    ->mapWithKeys(fn (mixed $id): array => [(int) $id => true]);

                foreach ($rows as $row) {
                    $updates = [];

                    if ($row->baseline_operation_run_id === null && is_numeric($row->baseline_run_id)) {
                        $candidate = $operationRunIdByLegacyRunId->get((int) $row->baseline_run_id);

                        if (is_numeric($candidate) && $existingOperationRunIds->has((int) $candidate)) {
                            $updates['baseline_operation_run_id'] = (int) $candidate;
                        }
                    }

                    if ($row->current_operation_run_id === null && is_numeric($row->current_run_id)) {
                        $candidate = $operationRunIdByLegacyRunId->get((int) $row->current_run_id);

                        if (is_numeric($candidate) && $existingOperationRunIds->has((int) $candidate)) {
                            $updates['current_operation_run_id'] = (int) $candidate;
                        }
                    }

                    if ($updates === []) {
                        continue;
                    }

                    DB::table('findings')
                        ->where('id', (int) $row->id)
                        ->update($updates);
                }
            });
    }

    public function down(): void
    {
        if (! Schema::hasTable('findings')) {
            return;
        }

        $updates = [];

        if (Schema::hasColumn('findings', 'baseline_operation_run_id')) {
            $updates['baseline_operation_run_id'] = null;
        }

        if (Schema::hasColumn('findings', 'current_operation_run_id')) {
            $updates['current_operation_run_id'] = null;
        }

        if ($updates === []) {
            return;
        }

        DB::table('findings')->update($updates);
    }
};
