<?php

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

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

        $this->addColumn('qty_in', fn (Blueprint $table) => $table->unsignedInteger('qty_in')->default(0)->after('quantity_delta'));
        $this->addColumn('qty_out', fn (Blueprint $table) => $table->unsignedInteger('qty_out')->default(0)->after('qty_in'));
        $this->addColumn('before_qty', fn (Blueprint $table) => $table->integer('before_qty')->default(0)->after('qty_out'));
        $this->addColumn('after_qty', fn (Blueprint $table) => $table->integer('after_qty')->default(0)->after('before_qty'));
        $this->addColumn('unit_cost', fn (Blueprint $table) => $table->decimal('unit_cost', 24, 8)->default(0)->after('variation_stock_after'));
        $this->addColumn('created_by', fn (Blueprint $table) => $table->unsignedBigInteger('created_by')->nullable()->index()->after('created_by_admin_id'));
        $this->addColumn('idempotency_key', fn (Blueprint $table) => $table->string('idempotency_key', 160)->nullable()->index()->after('note'));

        DB::table('stock_movements')->orderBy('id')->chunkById(500, function ($movements) {
            foreach ($movements as $movement) {
                $delta = (int) ($movement->quantity_delta ?? 0);
                DB::table('stock_movements')->where('id', $movement->id)->update([
                    'qty_in' => $delta > 0 ? $delta : 0,
                    'qty_out' => $delta < 0 ? abs($delta) : 0,
                    'before_qty' => (int) ($movement->stock_before ?? 0),
                    'after_qty' => (int) ($movement->stock_after ?? 0),
                    'created_by' => $movement->created_by_admin_id ?? null,
                    'idempotency_key' => $this->movementKey($movement),
                ]);
            }
        });
    }

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

        Schema::table('stock_movements', function (Blueprint $table) {
            foreach (['idempotency_key', 'created_by', 'unit_cost', 'after_qty', 'before_qty', 'qty_out', 'qty_in'] as $column) {
                if (Schema::hasColumn('stock_movements', $column)) {
                    $table->dropColumn($column);
                }
            }
        });
    }

    private function addColumn(string $column, callable $definition): void
    {
        if (Schema::hasColumn('stock_movements', $column)) {
            return;
        }

        Schema::table('stock_movements', function (Blueprint $table) use ($definition) {
            $definition($table);
        });
    }

    private function movementKey(object $movement): ?string
    {
        if (empty($movement->source_type) || empty($movement->source_id)) {
            return null;
        }

        return implode(':', [
            $movement->source_type,
            $movement->source_id,
            $movement->item_id ?? 0,
            $movement->variation_type ?? '',
            $movement->movement_type ?? '',
            $movement->quantity_delta ?? 0,
        ]);
    }
};
